运行时创建内存效率高的常量的技术
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);
但是,这肯定有一些缺点。证券交易所会不时推出新板。当这样的事件发生时,我需要
- 在枚举中添加新成员
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
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;
}
目前,我在我的应用程序中有以下设计,它使用 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);
但是,这肯定有一些缺点。证券交易所会不时推出新板。当这样的事件发生时,我需要
- 在枚举中添加新成员
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
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;
}