java - 为什么 indexOf() 和 contains() 在 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));
如果我使用原始工作方法,则输出:
Animal Farm has been bought
Animal Farm is already bought
使用 contains() 不起作用的方法的输出
Animal Farm has been bought
Animal Farm has been bought
使用 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;
}
这是我不知道为什么它不起作用的方法,我打算如何使这个方法起作用,如果变量searchItem返回 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;
}
}
这也没有按我的预期工作。我希望这种方法起作用的方式是,当我找到我正在寻找的元素的索引位置,然后将它与列表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;
}
商店类创建任意商店类
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);
}
基本项目类添加任何类型的项目
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;
}
}
具有添加和搜索方法的实际书店类
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;
}
}
显然,我知道我对它应该如何工作所做的假设是错误的,问题在于那些内置方法以及我希望它们如何工作,但事实并非如此。
解决方案
解决方案:
您必须实现equals
and hashCode
in Item
,因为contains
依赖于equals
.
如果默认情况下不覆盖equals
Java,则使用引用相等。
从以下文档contains
:
true
如果此列表包含指定的元素,则返回。更正式地说,true
当且仅当此列表包含至少一个元素时才e
返回(o==null ? e==null : o.equals(e))
.
覆盖规则equals
:
部分摘自此处:Java SE 定义了equals
必须履行的合同。equals
方法必须是:
- reflexive : 一个对象必须等于它自己
- 对称:
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
这两种方法中的字段来确定它们的返回值。
只有遵循这些规则,我们才能期望标准库中的数据结构(或任何其他数据结构)能够正常工作。
推荐阅读
- python - 矩阵(2x1)中的数字数组而不改变其形状
- python - 在 python 中将 Yes 转换为 1 和 No 转换为 0
- apache-kafka - kafka集群支持多少个stream
- javascript - 我可以将字符串传递给 javascript 函数并将其用作对象的属性吗?
- python - python正则表达式 - 在文件中搜索模式
- ms-access - Filtering a MS-Access recordset based on records in another recordset
- git - 如何删除链接存储库中的 git 远程标签?
- amazon-web-services - EBS 中的使用量和可用量有什么区别
- c - 以正确的方式使用 long long 数据类型
- json - 还需要带有其键的 jq 输出