如何检查 Java 中 LinkedHashMap 的相等性 - 还要考虑插入顺序?
How to check equality of LinkedHashMaps in Java - also taking the insertion-order into account?
我想检查 Java 中两个 LinkedHashMap 的相等性。
equals()
方法位于 AbstractMap
中,仅检查比较列表中是否存在具有相同键和值的条目。因此,不检查插入顺序:
package com.Whosebug.tests;
import java.util.LinkedHashMap;
public class LinkedHashMapEqualsTest {
public static void main(String[] args) {
LinkedHashMap<String, String> lhm1 = new LinkedHashMap<String, String>();
lhm1.put("A", "1");
lhm1.put("B", "2");
lhm1.put("C", "3");
LinkedHashMap<String, String> lhm2 = new LinkedHashMap<String, String>();
lhm2.put("A", "1");
lhm2.put("B", "2");
lhm2.put("C", "3");
LinkedHashMap<String, String> lhm3 = new LinkedHashMap<String, String>();
lhm3.put("A", "1");
lhm3.put("C", "3");
lhm3.put("B", "2");
LinkedHashMap<String, String> lhm4 = new LinkedHashMap<String, String>();
lhm4.put("A", "1");
lhm4.put("B", "2");
LinkedHashMap<String, String> lhm5 = new LinkedHashMap<String, String>();
lhm5.put("A", "2");
lhm5.put("B", "2");
lhm5.put("C", "3");
if(lhm1.equals(lhm1)) {
System.out.println("Positive control. - SUCCESS");
}
if(lhm1.equals(lhm2)) {
System.out.println("lhm1 does equal lhm2; as expected. - SUCCESS");
}
if(lhm1.equals(lhm3)) {
System.out.println("lhm1 does equal lhm3, although the insert-order is different.");
}
if(!lhm1.equals(lhm4)) {
System.out.println("Negative control 1. - SUCCESS");
}
if(!lhm1.equals(lhm5)) {
System.out.println("Negative control 2. - SUCCESS");
}
}
}
我如何检查两个比较列表的插入顺序是否相同?
无需任何扩展即可执行此操作的天真方法是使用 toString()
输出:
public static <K,V> boolean equalConsideringInsertionOrder(
Map<K,V> left, Map<K,V> right){
return left.toString().equals(right.toString());
}
但正如评论中指出的那样,这个版本有些问题。 toString() 不是规范格式,因此不应该那样使用。
一个更详细、更高效、更正确的版本应该是这样的:
public static <K, V> boolean equalConsideringInsertionOrder(
Map<K, V> left, Map<K, V> right) {
Iterator<Map.Entry<K, V>> leftIterator = left.entrySet().iterator();
Iterator<Map.Entry<K, V>> rightIterator = right.entrySet().iterator();
while (leftIterator.hasNext() && rightIterator.hasNext()) {
Map.Entry<K, V> leftEntry = leftIterator.next();
Map.Entry<K, V> rightEntry = rightIterator.next();
if (!Objects.equals(leftEntry.getKey(), rightEntry.getKey())
|| !Objects.equals(leftEntry.getValue(),rightEntry.getValue())) {
return false;
}
}
return !leftIterator.hasNext() && !rightIterator.hasNext();
}
我可能不会覆盖 LinkedHashMap
的 equals()
,但会提供一个辅助方法,例如像这样(灵感来自 AbstractList#equals(...)
):
public static <K, V> boolean linkedEquals( LinkedHashMap<K, V> left, LinkedHashMap<K, V> right) {
Iterator<Entry<K, V>> leftItr = left.entrySet().iterator();
Iterator<Entry<K, V>> rightItr = right.entrySet().iterator();
while ( leftItr.hasNext() && rightItr.hasNext()) {
Entry<K, V> leftEntry = leftItr.next();
Entry<K, V> rightEntry = rightItr.next();
//AbstractList does null checks here but for maps we can assume you never get null entries
if (! leftEntry.equals(rightEntry))
return false;
}
return !(leftItr.hasNext() || rightItr.hasNext());
}
然后你像if( linkedEquals(lhm1, lhm3) )
一样使用它。
编辑:
根据要求,另一种产生较低性能(由于多次不必要的迭代)但需要编写较少代码的方法是将条目集转换为列表并进行比较,例如像这样:
if( new ArrayList<>(lhm1.entrySet()).equals(new ArrayList<>(lhm3.entrySet()) ) { ... }
我想检查 Java 中两个 LinkedHashMap 的相等性。
equals()
方法位于 AbstractMap
中,仅检查比较列表中是否存在具有相同键和值的条目。因此,不检查插入顺序:
package com.Whosebug.tests;
import java.util.LinkedHashMap;
public class LinkedHashMapEqualsTest {
public static void main(String[] args) {
LinkedHashMap<String, String> lhm1 = new LinkedHashMap<String, String>();
lhm1.put("A", "1");
lhm1.put("B", "2");
lhm1.put("C", "3");
LinkedHashMap<String, String> lhm2 = new LinkedHashMap<String, String>();
lhm2.put("A", "1");
lhm2.put("B", "2");
lhm2.put("C", "3");
LinkedHashMap<String, String> lhm3 = new LinkedHashMap<String, String>();
lhm3.put("A", "1");
lhm3.put("C", "3");
lhm3.put("B", "2");
LinkedHashMap<String, String> lhm4 = new LinkedHashMap<String, String>();
lhm4.put("A", "1");
lhm4.put("B", "2");
LinkedHashMap<String, String> lhm5 = new LinkedHashMap<String, String>();
lhm5.put("A", "2");
lhm5.put("B", "2");
lhm5.put("C", "3");
if(lhm1.equals(lhm1)) {
System.out.println("Positive control. - SUCCESS");
}
if(lhm1.equals(lhm2)) {
System.out.println("lhm1 does equal lhm2; as expected. - SUCCESS");
}
if(lhm1.equals(lhm3)) {
System.out.println("lhm1 does equal lhm3, although the insert-order is different.");
}
if(!lhm1.equals(lhm4)) {
System.out.println("Negative control 1. - SUCCESS");
}
if(!lhm1.equals(lhm5)) {
System.out.println("Negative control 2. - SUCCESS");
}
}
}
我如何检查两个比较列表的插入顺序是否相同?
无需任何扩展即可执行此操作的天真方法是使用 toString()
输出:
public static <K,V> boolean equalConsideringInsertionOrder(
Map<K,V> left, Map<K,V> right){
return left.toString().equals(right.toString());
}
但正如评论中指出的那样,这个版本有些问题。 toString() 不是规范格式,因此不应该那样使用。
一个更详细、更高效、更正确的版本应该是这样的:
public static <K, V> boolean equalConsideringInsertionOrder(
Map<K, V> left, Map<K, V> right) {
Iterator<Map.Entry<K, V>> leftIterator = left.entrySet().iterator();
Iterator<Map.Entry<K, V>> rightIterator = right.entrySet().iterator();
while (leftIterator.hasNext() && rightIterator.hasNext()) {
Map.Entry<K, V> leftEntry = leftIterator.next();
Map.Entry<K, V> rightEntry = rightIterator.next();
if (!Objects.equals(leftEntry.getKey(), rightEntry.getKey())
|| !Objects.equals(leftEntry.getValue(),rightEntry.getValue())) {
return false;
}
}
return !leftIterator.hasNext() && !rightIterator.hasNext();
}
我可能不会覆盖 LinkedHashMap
的 equals()
,但会提供一个辅助方法,例如像这样(灵感来自 AbstractList#equals(...)
):
public static <K, V> boolean linkedEquals( LinkedHashMap<K, V> left, LinkedHashMap<K, V> right) {
Iterator<Entry<K, V>> leftItr = left.entrySet().iterator();
Iterator<Entry<K, V>> rightItr = right.entrySet().iterator();
while ( leftItr.hasNext() && rightItr.hasNext()) {
Entry<K, V> leftEntry = leftItr.next();
Entry<K, V> rightEntry = rightItr.next();
//AbstractList does null checks here but for maps we can assume you never get null entries
if (! leftEntry.equals(rightEntry))
return false;
}
return !(leftItr.hasNext() || rightItr.hasNext());
}
然后你像if( linkedEquals(lhm1, lhm3) )
一样使用它。
编辑:
根据要求,另一种产生较低性能(由于多次不必要的迭代)但需要编写较少代码的方法是将条目集转换为列表并进行比较,例如像这样:
if( new ArrayList<>(lhm1.entrySet()).equals(new ArrayList<>(lhm3.entrySet()) ) { ... }