Java 字符串或对象比较的哈希集
Java hashset of strings or objects comparision
我开发了一个 Java 模块,用于检查 JFrame 表单上的任何组件是否已更改其值(文本)并将该组件放入 JFrame 的 HashSet 中。
目前,我在value/text更改时将组件名称(String类型)放入HashSet。
我又想到,如果我将 Object(具有更改值的组件)放入 HashSet 中,认为与使用组件名称(String)相比可能会节省时间。
这里,我的问题是faster/efficent在
之间
- 使用 String(组件名称) 到 HashSet,或者
- 将对象(组件本身)用于 HashSet?
总之,也许,哪个更便宜?字符串比较还是对象比较?
谢谢,
JB
插入的便宜不应该是开发阶段的首要问题。 equals
对象的方法通常执行起来并不昂贵。你应该从任何能给你带来最少代码复杂性的东西开始,只有当性能成为一个问题时才开始以效率为目标。此外,除非插入到集合中的项目在 hashcode
上发生冲突,否则甚至不会进行比较。
Martin 的回答是正确的,不要再担心性能了,除非你确定你有一个严重的性能问题,这对你的产品有实际的负面影响。
但要回答问题:
如果您使用 HashSet
,那么性能将取决于组件是否实现了 hashCode()
,如果实现了,它们的 hashCode()
计算成本是多少。大多数机会是他们甚至没有实现 hashCode()
,因此他们的哈希码本质上将是他们的 Identity Hash Codes,(查一下,)所以将对象放在地图中字符串的速度将无限快。我们这里讨论的是时钟周期。
这同样适用于比较:组件可能也没有实现 equals()
,因此它们将通过引用进行比较,这将比比较字符串稍微快一些。
如果 "probably" 对你来说不够好,如果你不能查看这些组件的源代码,那么你可以使用 IdentityHashSet
而不是 HashSet
,以保证只使用身份哈希码和参考比较。
但谁在乎呢。迄今为止最好的方法是做任何更简单、更容易理解和更易于维护的事情。
刚刚在Java中测试了自己对HashSet元素类型的两种选择。
结果说明了我的一切想法。
HashSet element type: Object, experiment count: 1000, Elapsed time: 16ms
HashSet element type: Object, experiment count: 1000, Elapsed time: 8ms
HashSet element type: Object, experiment count: 1000, Elapsed time: 8ms
HashSet element type: String, experiment count: 1000, Elapsed time: 124ms
HashSet element type: String, experiment count: 1000, Elapsed time: 110ms
HashSet element type: String, experiment count: 1000, Elapsed time: 130ms
要知道,Java的执行速度还是有一些不好的名声的。
您会使用哪种 HashSet 元素类型?
这是显示上述结果的我的代码。
boolean StringUsed = true;
changedComponents = new HashSet<Component>() {};
changedComponentNames = new HashSet<String>() {};
private void changeValueManyTimes() {
long start = System.currentTimeMillis();
for (int i = 0; i<count; i++) {
recordStatisticsCheckBox.setSelected
(!recordStatisticsCheckBox.isSelected());
}
long stop = System.currentTimeMillis();
System.out.print("HashSet element type: " +
(StringUsed ? "String" : "Object") + ", experiment count: " + count);
System.out.println(", Elapsed time: " + (stop - start) + "ms");
System.out.println("");
}
public static int count = 1000;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
StringUsed = false;
changeValueManyTimes();
}
private void recordStatisticsCheckBoxStateChanged
(javax.swing.event.ChangeEvent evt) {
recordStatisticsCheckBoxActionPerformed(null);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
StringUsed = true;
changeValueManyTimes();
}
private void recordStatisticsCheckBoxActionPerformed
(java.awt.event.ActionEvent evt) {
if (StringUsed) {
if (recordStatisticsCheckBox.isSelected() == origSelection) {
changedComponents.remove(recordStatisticsCheckBox);
} else {
changedComponents.add(recordStatisticsCheckBox);
}
changeSaveEnabledIfNeeded();
} else {
if (recordStatisticsCheckBox.isSelected() == origSelection) {
changedComponentNames.remove(recordStatisticsCheckBox.getName());
} else {
changedComponentNames.add(recordStatisticsCheckBox.getName());
}
changeSaveEnabledIfNeeded();
}
}
private void changeSaveEnabledIfNeeded() {
if (changedComponents.size() == 0)
saveButton.setEnabled(false);
else
saveButton.setEnabled(true);
}
我开发了一个 Java 模块,用于检查 JFrame 表单上的任何组件是否已更改其值(文本)并将该组件放入 JFrame 的 HashSet 中。
目前,我在value/text更改时将组件名称(String类型)放入HashSet。
我又想到,如果我将 Object(具有更改值的组件)放入 HashSet 中,认为与使用组件名称(String)相比可能会节省时间。
这里,我的问题是faster/efficent在
之间- 使用 String(组件名称) 到 HashSet,或者
- 将对象(组件本身)用于 HashSet?
总之,也许,哪个更便宜?字符串比较还是对象比较?
谢谢,
JB
插入的便宜不应该是开发阶段的首要问题。 equals
对象的方法通常执行起来并不昂贵。你应该从任何能给你带来最少代码复杂性的东西开始,只有当性能成为一个问题时才开始以效率为目标。此外,除非插入到集合中的项目在 hashcode
上发生冲突,否则甚至不会进行比较。
Martin 的回答是正确的,不要再担心性能了,除非你确定你有一个严重的性能问题,这对你的产品有实际的负面影响。
但要回答问题:
如果您使用 HashSet
,那么性能将取决于组件是否实现了 hashCode()
,如果实现了,它们的 hashCode()
计算成本是多少。大多数机会是他们甚至没有实现 hashCode()
,因此他们的哈希码本质上将是他们的 Identity Hash Codes,(查一下,)所以将对象放在地图中字符串的速度将无限快。我们这里讨论的是时钟周期。
这同样适用于比较:组件可能也没有实现 equals()
,因此它们将通过引用进行比较,这将比比较字符串稍微快一些。
如果 "probably" 对你来说不够好,如果你不能查看这些组件的源代码,那么你可以使用 IdentityHashSet
而不是 HashSet
,以保证只使用身份哈希码和参考比较。
但谁在乎呢。迄今为止最好的方法是做任何更简单、更容易理解和更易于维护的事情。
刚刚在Java中测试了自己对HashSet元素类型的两种选择。 结果说明了我的一切想法。
HashSet element type: Object, experiment count: 1000, Elapsed time: 16ms
HashSet element type: Object, experiment count: 1000, Elapsed time: 8ms
HashSet element type: Object, experiment count: 1000, Elapsed time: 8ms
HashSet element type: String, experiment count: 1000, Elapsed time: 124ms
HashSet element type: String, experiment count: 1000, Elapsed time: 110ms
HashSet element type: String, experiment count: 1000, Elapsed time: 130ms
要知道,Java的执行速度还是有一些不好的名声的。 您会使用哪种 HashSet 元素类型?
这是显示上述结果的我的代码。
boolean StringUsed = true;
changedComponents = new HashSet<Component>() {};
changedComponentNames = new HashSet<String>() {};
private void changeValueManyTimes() {
long start = System.currentTimeMillis();
for (int i = 0; i<count; i++) {
recordStatisticsCheckBox.setSelected
(!recordStatisticsCheckBox.isSelected());
}
long stop = System.currentTimeMillis();
System.out.print("HashSet element type: " +
(StringUsed ? "String" : "Object") + ", experiment count: " + count);
System.out.println(", Elapsed time: " + (stop - start) + "ms");
System.out.println("");
}
public static int count = 1000;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
StringUsed = false;
changeValueManyTimes();
}
private void recordStatisticsCheckBoxStateChanged
(javax.swing.event.ChangeEvent evt) {
recordStatisticsCheckBoxActionPerformed(null);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
StringUsed = true;
changeValueManyTimes();
}
private void recordStatisticsCheckBoxActionPerformed
(java.awt.event.ActionEvent evt) {
if (StringUsed) {
if (recordStatisticsCheckBox.isSelected() == origSelection) {
changedComponents.remove(recordStatisticsCheckBox);
} else {
changedComponents.add(recordStatisticsCheckBox);
}
changeSaveEnabledIfNeeded();
} else {
if (recordStatisticsCheckBox.isSelected() == origSelection) {
changedComponentNames.remove(recordStatisticsCheckBox.getName());
} else {
changedComponentNames.add(recordStatisticsCheckBox.getName());
}
changeSaveEnabledIfNeeded();
}
}
private void changeSaveEnabledIfNeeded() {
if (changedComponents.size() == 0)
saveButton.setEnabled(false);
else
saveButton.setEnabled(true);
}