我想对对象进行更深入的字符串检查,以便能够执行以下操作:
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
但是使用以下完整代码
会对每个人产生错误/* 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"));
}
}
如果我是对的,列表对象应该使用equals()
和hashCode()
来评估包含的对象。
所以我@Override
他们并另外检查他们的字符串。
但它永远不会进入equals()
,因为没有输出MyObj.equals(Object)
。
答案 0 :(得分:7)
java.util.ArrayList#indexOf
在ArrayList内部用于contains()
。
有支票,
o.equals(elementData[i])
因此,字符串与您的对象进行比较,因此调用String.equals()
来检查相等性。
答案 1 :(得分:5)
您根本没有履行equals
合同:
equals方法在非null对象引用上实现等价关系:
因此,如果不遵守方法的合同,就不能指望预期的行为。
就是说,例如,什么保证你将在ArrayList中包含的对象上调用equals,而不是以其他方式调用,例如"hello".equals(new MyObj("hello"))
。你不能保证它,但因为equals
通常应该是对称的而不是你不应该介意的。
答案 2 :(得分:1)
正如其他人所指出的那样,问题是你的 equals方法永远不会被调用。当您调用myList.contains("hello")
时,ArrayList
会检查"hello".equals(<MyObj>)
,而不是相反。
相反,我建议您正确实施equals
方法 ,以便将两个MyObject
个等同value
的实例视为相等,然后创建一个帮助方法像这样:
public boolean myContains(List<MyObj> list, String value) {
return list.contains(new MyObj(value));
}
答案 3 :(得分:0)
List<MyObj> myList = new ArrayList<MyObj>()
是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")));
答案 4 :(得分:0)
您要求列表将String
与MyObj
进行比较......它们永远不会“相等”。请改为使用地图:
Map<String, MyObj> map = new HashMap<String, MyObj>() {{
put("hello", new MyObj("hello"));
put("world", new MyObj("world"));
}};
然后你可以使用:
if (map.containsKey("hello"))
并获取相应的对象:
MyObj o = map.get("hello"); // get() returns null if key not found
答案 5 :(得分:0)
当包含执行时,调用的对象不等于String类中的对象。 和String实现检查instanceof是否该类是一个String来执行类似String的操作来确定答案。如果object不是String,则返回false;