运行时创建常量的技术,这是内存高效的

时间:2015-04-02 03:46:30

标签: java enums

目前,我的应用程序中有以下设计,即使用enum作为内存有效常量

public enum Board {
    Toronto    // Toronto stock Exchange
}

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

这是一种记忆效率高的方式。因为,如果证券交易所中有数千Stock,则只会创建一个Board个实例。

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

然而,这当然有一些缺点。证券交易所将不时推出新的董事会。发生此类事件时,我需要

  • 在枚举Board
  • 中添加新成员
  • 将应用程序编译并重新部署给用户

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类)

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

3 个答案:

答案 0 :(得分:2)

嗯,如何将电路板存放在一组或一张地图中?这样你就可以确保每个只有一个实例。

伪代码:

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
}

答案 1 :(得分:1)

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

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;
}

答案 2 :(得分:0)

在我看来,最好的解决方案是将Board添加到您的数据库中,当业务部门提出新的董事会时您必须更新数据库,您的董事会可能会日复一日地改变以适应业务需求,因此它不适合Constant或Enum