[英]Why indexOf() and contains() doesn't work as i intended in java?
// Objects for the bookstore I created
BookStore bookStore = new BookStore("Subu's Book Store","Perambur");
bookStore.addItem(new Item("Animal Farm",20));
bookStore.addItem(new Item("Animal Farm",20));
Output如果我用原来的工作方式:
Animal Farm has been bought
Animal Farm is already bought
Output 对于使用 contains() 不起作用的方法
Animal Farm has been bought
Animal Farm has been bought
Output 对于使用 indexof() 不起作用的方法
-1
Animal Farm has been bought
-1
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 1
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:459)
at com.company.subusproject.BookStore.searchItem(BookStore.java:41)
at com.company.subusproject.BookStore.addItem(BookStore.java:16)
at com.company.subusproject.Main.main(Main.java:11)
这是有效的原始方法
public boolean searchItem(Item item) {
for (int i = 0; i < this.myStocks.size(); i++) {
Item foundItem = this.myStocks.get(i);
if (foundItem.getName().equals((item.getName()))) {
return true;
}
}
return false;
}
这是我不知道为什么它不起作用的方法,我希望这个方法如何工作是,如果变量searchingItem返回 true 那么方法searchItem将返回,否则它返回 false
public boolean searchItem(Item item) {
// this method returns the boolean value true if found, if not returns false
boolean searchingItem = this.myStocks.contains(item);
if(searchingItem){
return true;
} else {
return false;
}
}
这也不按我的预期工作。 我打算使用此方法的方式是,当我找到要查找的元素的索引 position,然后将其与列表myStocks中可用的元素进行比较时,在这种情况下也不是这种情况。
public boolean searchItem(Item item) {
// this method returns the index number of the founded element, if not returns -1
int itemPosition = this.myStocks.indexOf(item); // this line always returns -1 in this scenario
for(int i=0; i<this.myStocks.size(); i++){
if(myStocks.get(itemPosition).getName().equals(myStocks.get(i).getName())){
return true;
}
}
return false;
}
Store class 创建任意店铺 class
public abstract class Store {
private String name;
private String address;
public Store(String name, String address) {
this.name = name;
this.address = address;
}
public abstract boolean addItem(Item item);
public abstract boolean removeItem(Item item);
public abstract boolean searchItem(Item item);
}
基础项目 class 添加任意项目
public class Item {
private String name;
private int price;
public Item(String name, int price){
this.name = name;
this.price = price;
}
public String getName(){
return this.name;
}
public int getPrice(){
return this.price;
}
}
实际的书店 class 其中有添加和搜索的方法
public class BookStore extends Store {
private List<Item> myStocks;
public BookStore(String name, String address) {
super(name, address);
this.myStocks = new ArrayList<>();
}
public boolean addItem(Item item) {
if (!searchItem(item)) {
this.myStocks.add(item);
System.out.println(item.getName() + " has been bought");
return true;
} else {
System.out.println(item.getName() + " is already bought");
return false;
}
}
public boolean searchItem(Item item) {
for (int i = 0; i < this.myStocks.size(); i++) {
Item foundItem = this.myStocks.get(i);
if(foundItem.getName().equals((this.myStocks.get(i).getName()))) {
return true;
}
}
return false;
}
}
显然,我知道我关于它应该如何工作的假设是错误的,问题在于那些内置方法以及我希望它们如何工作,但事实并非如此。
解决方案:
您必须在Item
中实现equals
和hashCode
,因为contains
依赖于equals
。
如果您不覆盖equals
Java,则默认使用引用相等。
从contains
的文档:
如果此列表包含指定元素,则返回
true
。 更正式地说,当且仅当此列表包含至少一个满足(o==null? e==null: o.equals(e))
的元素e
时才返回true
。
覆盖equals
的规则:
部分取自此处: equals
SE 定义了必须履行的合同。 equals
方法必须是:
x.equals(y)
必须返回与y.equals(x)
相同的结果x.equals(y)
和y.equals(z)
那么也x.equals(z)
equals
中的属性发生变化时, equals
的值才应该改变(不允许随机性) 为什么还要覆盖hashCode
?
也部分取自这里。 Java SE 还为hashCode
方法定义了一个契约。 仔细观察它可以看出hashCode
和equals
的关系有多密切。 hashCode
契约中的所有三个标准都以某种方式提到了equals
方法:
hashCode
的值可能仅在equals
中的属性发生变化时发生变化 我建议利用 IDE 来自动生成equals
和hashCode
,并且只使用这两种方法中的final
字段来确定它们的返回值。
只有遵循这些规则,我们才能期望标准库中的数据结构(或任何其他数据结构)能够正常工作。
您需要在Item
class 中实现equals()
方法, contains()
或indexOf()
在内部使用equals()
方法。 也因为它是合同中的,所以你必须实现hascode()
方法,这将确保没有违约。
如果您不实现哈希码,它将基于 JVM 实现占用 memory 位置,这将始终为等于 object 返回不同的 int,当您使用项目 object 作为 hashmap 中的键时,它会失败,它在哈希 81811498 时的性能也取决于 8111493关于 Hascode 实现(很长的主题,所以不详细介绍)。
阅读javadoc 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.