运行时创建内存效率高的常量的技术

Technique to runtime create constant which are memory efficient

目前,我在我的应用程序中有以下设计,它使用 enum 作为内存效率常数

public enum Board {
    Toronto    // Toronto stock Exchange
}

public class Stock {
    private final Board board;
    private final Code code;
    ....
}

这是一种节省内存的方法。因为,如果证券交易所中有数千个 Stock,则只会创建 1 个 Board 的实例。

Stock stock0 = new Stock(Code.newInstance("AAA.TO"), Board.Toronto);
Stock stock1 = new Stock(Code.newInstance("AAB.TO"), Board.Toronto);

但是,这肯定有一些缺点。证券交易所会不时推出新板。当这样的事件发生时,我需要


public enum Board {
    Toronto,   // Toronto stock Exchange
    TSXV       // New Toronto venture
}

Stock stock0 = new Stock(Code.newInstance("AAA.TO"), Board.Toronto);
Stock stock1 = new Stock(Code.newInstance("AAB.TO"), Board.Toronto);
Stock stock2 = new Stock(Code.newInstance("TRU.V"), Board.TSXV);

我想避免这样的不便。我的初步计划是

public class Board {
    private final String board;
    private Board(String board) {
        this.board = board;
    }
    public Board newInstance(String board) {
        return new Board(board);
    }
}

但是,这不是一种节省内存的方法。因为,将创建 Board 的多个实例。

// 2 Toronto board instance will be created! Not memory efficient when we have huge stock list.
Stock stock0 = new Stock(Code.newInstance("AAA.TO"), Board.newInstance("Toronto"));
Stock stock1 = new Stock(Code.newInstance("AAB.TO"), Board.newInstance("Toronto"));
Stock stock2 = new Stock(Code.newInstance("TRU.V"), Board.newInstance("TSXV"));

我在想,我可以应用什么样的数据结构,这样我就可以有一种内存高效的方式来表示常量(在我的上下文中,这意味着 Board class)

我不喜欢使用 String,因为我更喜欢类型安全,以区分 Board 和真正的 String

嗯,将棋盘存储在集合或地图中如何?这样你就可以确保每个实例只有一个实例。

伪代码:

public class Board {
    private static final Set<Board> boards = new HashSet<>();

    public static Board getInstance(String board) {
        //search if board already exists on boards set, if it is, return that instance; else, add to list and return the newly created instance.
    }
    //override equals and hashCode appropriately
}

我认为最好的解决方案是将Board添加到您的数据库中,并且当业务方提出新的board时您必须更新您的数据库,您的Board可能每天都在变化以适应业务需求所以它不适合对于常量或枚举

这是一种线程安全的方式。我不太确定这样的实现是否可以被视为享元模式。但是,我已尽最大努力确保它是线程安全的。如果您发现任何可能的错误,请随时修改代码。

import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @author yccheok
 */
public class Board {
    private Board(String board) {
        this.board = board;
    }

    public static Board newInstance(String board) {
        if (board == null) {
            throw new java.lang.IllegalArgumentException("board cannot be null");
        }

        Board result = map.get(board);
        if (result == null) {
            final Board instance = new Board(board);
            result = map.putIfAbsent(board, instance);
            if (result == null) {
                return instance;
            }
        }

        assert(result != null);
        return result;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + board.hashCode();

        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof Board)) {
            return false;
        }

        return this.board.equals(((Board)o).board);
    }

    @Override
    public String toString() {
        return board;
    }

    // Avoid using interface. We want it to be fast!
    private static final ConcurrentHashMap<String, Board> map = new ConcurrentHashMap<>();
    private final String board;
}