使用 Java ArrayList contains() 评估包含字符串的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19451212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Evaluating objects containing Strings with Java ArrayList contains()
提问by dtrunk
I would like to do a deeper String check of Objects to be able to do the following:
我想对对象进行更深入的字符串检查,以便能够执行以下操作:
List<MyObj> myList = new ArrayList<MyObj>() {{
add(new MyObj("hello"));
add(new MyObj("world"));
}};
System.out.println(myList.contains("hello")); // true
System.out.println(myList.contains("foo")); // false
System.out.println(myList.contains("world")); // true
But getting false on each one with the following full code
但是使用以下完整代码对每个人都造成错误
/* Name of the class has to be "Main" only if the class is public. */
class Ideone {
public static class MyObj {
private String str;
private int hashCode;
public MyObj(String str) {
this.str = str;
}
public @Override boolean equals(Object obj) {
System.out.println("MyObj.equals(Object)");
if (obj == this) {
return true;
}
if (obj instanceof String) {
String strObj = (String) obj;
return strObj.equals(str);
}
return false;
}
public @Override int hashCode() {
if (hashCode == 0) {
hashCode = 7;
for (int i = 0; i < str.length(); ++i) {
hashCode = hashCode * 31 + str.charAt(i);
}
}
return hashCode;
}
}
public static final MyObj obj1 = new MyObj("hello");
public static final MyObj obj2 = new MyObj("world");
public static void main (String[] args) throws java.lang.Exception {
List<MyObj> myList = new ArrayList<MyObj>() {{
add(obj1);
add(obj2);
}};
System.out.println(myList.contains("hello"));
System.out.println(myList.contains("foo"));
System.out.println(myList.contains("world"));
}
}
If I'm right the List Object should use equals()
and hashCode()
to evaluate containing Objects.
So I @Override
them and check their Strings additionally.
But it never gets into equals()
as there's no output MyObj.equals(Object)
.
如果我是对的,列表对象应该使用equals()
并hashCode()
评估包含的对象。所以我@Override
他们并额外检查他们的字符串。但它永远不会进入,equals()
因为没有输出MyObj.equals(Object)
。
采纳答案by Admit
java.util.ArrayList#indexOf
is used internally in ArrayList for contains()
.
java.util.ArrayList#indexOf
在 ArrayList 内部用于contains()
.
There is a check,
有支票,
o.equals(elementData[i])
So there is comparison of string with your object, so String.equals()
is invoked for check of equality.
因此将字符串与您的对象进行比较,因此String.equals()
调用它来检查相等性。
回答by Hyman
You are not fulfilling the equals
contract at all:
您根本没有履行equals
合同:
The equals method implements an equivalence relation on non-null object references:
equals 方法在非空对象引用上实现等价关系:
- It is reflexive: for any non-null reference value x, x.equals(x) should return true. Yours is not reflexive.
- It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. Yours is not symmetric.
- It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. Yours is not transitive
- It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
- For any non-null reference value x, x.equals(null) should return false.
- 它是自反的:对于任何非空引用值 x,x.equals(x) 应该返回 true。你的不是反射性的。
- 它是对称的:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。你的不对称。
- 它是可传递的:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,那么 x.equals(z) 应该返回 true。你的不是可传递的
- 它是一致的:对于任何非空引用值 x 和 y,x.equals(y) 的多次调用始终返回 true 或始终返回 false,前提是对象的 equals 比较中使用的信息没有被修改。
- 对于任何非空引用值 x,x.equals(null) 应返回 false。
So without respecting the contract for the method you can't expect intended behavior.
因此,如果不遵守该方法的约定,您就不能期望预期的行为。
Just for example, what guarantees you that equals is going to be called on the object contained in the ArrayList and not in the other way, eg "hello".equals(new MyObj("hello"))
. You have no guarantees about it but since equals
is normally supposed to be symmetric than you shouldn't mind.
举例来说,什么保证你将在 ArrayList 中包含的对象上调用 equals 而不是以其他方式调用,例如"hello".equals(new MyObj("hello"))
. 你不能保证它,但因为equals
通常应该是对称的,而不是你不应该介意。
回答by Debojit Saikia
List<MyObj> myList = new ArrayList<MyObj>()
is a list of MyObj
, so you need to use MyObj
while checking myList.contains
:
是一个列表MyObj
,因此您需要MyObj
在检查时使用myList.contains
:
System.out.println(myList.contains(new MyObj("hello")));
System.out.println(myList.contains(new MyObj("foo")));
System.out.println(myList.contains(new MyObj("world")));
回答by Bohemian
You're asking the List to compare a String
to a MyObj
... They are never going to be "equal". Try a map instead:
您要求 List 将 aString
与 a进行比较MyObj
……它们永远不会“相等”。尝试使用地图:
Map<String, MyObj> map = new HashMap<String, MyObj>() {{
put("hello", new MyObj("hello"));
put("world", new MyObj("world"));
}};
Then you can use:
然后你可以使用:
if (map.containsKey("hello"))
and to get the corresponding object:
并获取相应的对象:
MyObj o = map.get("hello"); // get() returns null if key not found
回答by tobias_k
As pointed out by others, the problem is that yourequals method is never called. When you invoke myList.contains("hello")
, ArrayList
checks whether "hello".equals(<MyObj>)
, not the other way around.
正如其他人所指出的,问题是您的equals 方法从未被调用。当您调用 时myList.contains("hello")
,ArrayList
检查是否"hello".equals(<MyObj>)
,而不是相反。
Instead, I recommend implementing your equals
method properly, so that two MyObject
instances with equal value
are considered equal, and then create a helper method like this:
相反,我建议正确实现您的equals
方法,以便将具有相等的两个实例视为相等,然后创建一个像这样的辅助方法:MyObject
value
public boolean myContains(List<MyObj> list, String value) {
return list.contains(new MyObj(value));
}
回答by Luke
It is not equals of your object called when contains executes but the one from String class. And String implementation checks with instanceof whether the class is a String to perform String-like operations to determine the answer. If object is not a String it will return false;
它不等于您在包含执行时调用的对象,而是来自 String 类的对象。并且 String 实现通过 instanceof 检查该类是否为 String 以执行类似 String 的操作以确定答案。如果 object 不是 String,它将返回 false;