Google guava ImmutableList equals Method returns 与 java.utils.List 不同的结果,破坏了 List-Interface 契约?
Google guava ImmutableList equals Method returns a different result than java.utils.List, breaking List-Interface contract?
我只是偶然发现了问题,我不太确定是我遗漏了什么,还是什么东西坏了。
我正在使用 google 番石榴 (19.0)。当我测试 ImmutableLists 的相等性时,发生了一些可疑的事情。
在 ImmutableList 的 Javadoc 中说 ImmutableList 实现了 java.util.List 接口
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html
因此,我假设 ImmutableList 的 equals 方法将遵循 java.util.List 给出的合同,并且 return 相同列表的相同结果
在 List.equals() 中说
“[...]换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。此定义确保 equals 方法在 List 接口的不同实现中正常工作。”
https://docs.oracle.com/javase/6/docs/api/java/util/List.html#equals(java.lang.Object)
现在想想这个小代码示例
ImmutableList.Builder<String> builder1 = new ImmutableList.Builder<>();
builder1.add("Test1");
List<String> list1 = builder1.build();
ImmutableList.Builder<String> builder2 = new ImmutableList.Builder<>();
builder1.add("Test1");
List<String> list2 = builder2.build();
System.out.println(list1.equals(list2));
//--> false
List<String> defaultList1 = new LinkedList<>();
defaultList1.add("Test1");
List<String> defaultList2 = new LinkedList<>();
defaultList2.add("Test1");
System.out.println(defaultList1.equals(defaultList2));
// --> true
现在,您期望得到什么输出?
我预计这两个测试都是 true。
但实际输出是不同的。正如预期的那样,java 版本等于 return 为真。但是 guava 版本 returns false.
如果您现在查看 javadoc for google immutableList,它说 equals 方法 returns o1==o2(这违反了列表接口合同)。所以我明白为什么我的代码示例会这样工作。
我认为这不是 google 人的 "bug",而是我对接口和契约的理解有问题
您正在将元素添加到同一个构建器(在您的例子中为 builder1)。见下文。所以 builder2 实际上什么都没有,hance 等于 return false.
ImmutableList.Builder<String> builder1 = new ImmutableList.Builder<>();
builder1.add("Test1"); // builder1
List<String> list1 = builder1.build();
ImmutableList.Builder<String> builder2 = new ImmutableList.Builder<>();
builder1.add("Test1"); // again builder1
List<String> list2 = builder2.build();
System.out.println(list1.equals(list2));
//--> false
List<String> defaultList1 = new LinkedList<>();
defaultList1.add("Test1");
List<String> defaultList2 = new LinkedList<>();
defaultList2.add("Test1");
System.out.println(defaultList1.equals(defaultList2));
// --> true
我只是偶然发现了问题,我不太确定是我遗漏了什么,还是什么东西坏了。
我正在使用 google 番石榴 (19.0)。当我测试 ImmutableLists 的相等性时,发生了一些可疑的事情。
在 ImmutableList 的 Javadoc 中说 ImmutableList 实现了 java.util.List 接口 http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html
因此,我假设 ImmutableList 的 equals 方法将遵循 java.util.List 给出的合同,并且 return 相同列表的相同结果
在 List.equals() 中说 “[...]换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。此定义确保 equals 方法在 List 接口的不同实现中正常工作。”
https://docs.oracle.com/javase/6/docs/api/java/util/List.html#equals(java.lang.Object)
现在想想这个小代码示例
ImmutableList.Builder<String> builder1 = new ImmutableList.Builder<>();
builder1.add("Test1");
List<String> list1 = builder1.build();
ImmutableList.Builder<String> builder2 = new ImmutableList.Builder<>();
builder1.add("Test1");
List<String> list2 = builder2.build();
System.out.println(list1.equals(list2));
//--> false
List<String> defaultList1 = new LinkedList<>();
defaultList1.add("Test1");
List<String> defaultList2 = new LinkedList<>();
defaultList2.add("Test1");
System.out.println(defaultList1.equals(defaultList2));
// --> true
现在,您期望得到什么输出?
我预计这两个测试都是 true。 但实际输出是不同的。正如预期的那样,java 版本等于 return 为真。但是 guava 版本 returns false.
如果您现在查看 javadoc for google immutableList,它说 equals 方法 returns o1==o2(这违反了列表接口合同)。所以我明白为什么我的代码示例会这样工作。
我认为这不是 google 人的 "bug",而是我对接口和契约的理解有问题
您正在将元素添加到同一个构建器(在您的例子中为 builder1)。见下文。所以 builder2 实际上什么都没有,hance 等于 return false.
ImmutableList.Builder<String> builder1 = new ImmutableList.Builder<>();
builder1.add("Test1"); // builder1
List<String> list1 = builder1.build();
ImmutableList.Builder<String> builder2 = new ImmutableList.Builder<>();
builder1.add("Test1"); // again builder1
List<String> list2 = builder2.build();
System.out.println(list1.equals(list2));
//--> false
List<String> defaultList1 = new LinkedList<>();
defaultList1.add("Test1");
List<String> defaultList2 = new LinkedList<>();
defaultList2.add("Test1");
System.out.println(defaultList1.equals(defaultList2));
// --> true