在任务中共享TaskKey,哪一个更好?还有其他更好的方法吗?
way1由一个密钥对象共享。这样,客户端代码(Task Queue)更易于编写以配置任务表。但是每个任务都必须浪费内存来存储TaskKey对象。
class TaskKey {
int key1;
int key2;
// key3...
TaskKey(int key1, int key2) {
this.key1 = key1;
this.key2 = key2;
}
}
abstract class Task implements Cloneable {
TaskKey key;
int taskData;
Task(TaskKey key) {
this.key = key;
}
int getKey1() {
return key.key1;
}
int getKey2() {
return key.key2;
}
Task newInstance(int taskData) {
Task task = (Task) clone();
task.taskData = taskData;
return task;
}
abstract void doSomething();
}
class TaskQueue {
Task[][] taskTable;
void addTask(Task task) {
taskTable[task.getKey1()][task.getKey2()] = task;
}
void config() {
addTask(new Task(new TaskKey(1, 1)) {
void doSomething() {}
});
addTask(new Task(new TaskKey(1, 2)) {
void doSomething() {}
});
addTask(new Task(new TaskKey(2, 1)) {
void doSomething() {}
});
}
Queue<Task> queue;
void put(int key1, int key2, int taskData) {
Task task = taskTable[key1][key2];
queue.add(task.newInstance(taskData));
}
}
way2由任务类共享。这样,客户端代码(Task Queue)很难写入配置任务表(覆盖Task的getKey()方法)。但是每个任务都不需要浪费内存来存储TaskKey对象,因为关键信息由具体的Task类共享。
abstract class Task implements Cloneable {
int taskData;
abstract int getKey1();
abstract int getKey2();
abstract void doSomething();
Task newInstance(int taskData) {
Task task = (Task) clone();
task.taskData = taskData;
return task;
}
}
class TaskQueue {
Task[][] taskTable;
void addTask(Task task) {
taskTable[task.getKey1()][task.getKey2()] = task;
}
void config() {
addTask(new Task() {
int getKey1() { return 1; }
int getKey2() { return 1; }
void doSomething() {}
});
addTask(new Task() {
int getKey1() { return 1; }
int getKey2() { return 2; }
void doSomething() {}
});
addTask(new Task() {
int getKey1() { return 2; }
int getKey2() { return 1; }
void doSomething() {}
});
}
Queue<Task> queue;
void put(int key1, int key2, int taskData) {
Task task = taskTable[key1][key2];
queue.add(task.newInstance(taskData));
}
}
另一种方式1和方式2
interface TaskExecutor {
void exec(Task task);
}
class TaskKey {
int key1;
int key2;
int key3;
TaskExecutor executor;
}
class Task /*another way1*/ {
TaskKey key;
int taskData;// in fact it is not only a int
int getKey1() { // because i need to retrieve key1 from a task
return key.key1;
}
// also get methods for key2 key3
void exec(){
key.executor.exec(this);
}
}
class Task /*another way2*/ {
public final int key1;
public final int key2;
public final int key3;
private final TaskExecutor executor;
int taskData;
void exec(){
executor.exec(this);
}
}
答案 0 :(得分:0)
你可能不想第二种方式。对于像存储两个int
这样简单的事情,反射看起来有点矫枉过正。你从中获得的内存性能非常小,jvm必须更加努力地找出你的方法重载。它最终占用了更多的代码空间(你认为java编译器在哪里存储所有这些额外的信息?)以及减慢执行速度。
第一种方法是这样做的一种方式,但如果它只是存储两个int
s那么简单,您可能会考虑在Task
类中使用两个键而不是有一个单独的钥匙。
abstract class Task implements Cloneable {
int taskData;
int key1;
int key2;
Task(int key1_, int key2_) {
this.key1 = key1_;
this.key2 = key2_;
}
int getKey1() {
return key1;
}
int getKey2() {
return key2;
}
Task newInstance(int taskData) {
Task task = (Task) clone();
task.taskData = taskData;
return task;
}
abstract void doSomething();
}
但是,考虑到您已经有Task[][]
存储所有这些数据,似乎您不需要这样做,除非您需要获取key1
和{{的值1}}来自特定的key2
对象,您可以直接执行
Task
但是,如果您需要从特定的void addTask(Task task, int i, int j) {
taskTable[i][j] = task;
}
void config() {
addTask(new Task(), 1, 1);
}
对象获取key1
和key2
的值,则可以使用Task
代替{HashMap<TaskKey,Task>
1}}来存储您的数据。那样你就可以
Task[][]
虽然您可能需要使用您最喜欢的IDE生成HashMap<TaskKey,Task> taskTable;
void addTask(Task task, int i, int j) {
taskTable.put(new TaskKey(i,j), task);
}
Task getTask(int i, int j){
return taskTable.get(new TaskKey(i,j));
}
void config() {
addTask(new Task(), 1, 1);
}
和hashCode()
方法。这最终会保持内存效率,并且从阵列中获得相同的恒定时间访问。