【问题标题】:Suspicious call to Collection.contains method in ArrayListArrayList 中对 Collection.contains 方法的可疑调用
【发布时间】:2016-01-11 21:00:37
【问题描述】:

我收到警告,watchStore.contains(s) 是对 java.util.Collection#contains 的可疑调用。我该如何解决?我想使用contains() 来查找具有匹配序列号的特定对象。

public Watch findWatchBySerialNumber(long srch) {
    long s = srch;
    Watch watch = null;

    for(int i = 0; i < watchStore.size(); i++) {
        watch = watchStore.get(i);
            if(watchStore.contains(s)) {
                System.out.print("item found");
                return watch;
            }
    } 
    System.out.print("item not found");
    return null; // watch is not found.
}

【问题讨论】:

  • 你可以添加你得到的错误的堆栈跟踪
  • 你得到的确切错误是什么?
  • 什么是watchStore
  • watchStore 收藏有哪些内容?看还是看?
  • watchStore 来自哪里?

标签: java arraylist contains


【解决方案1】:

您可以使用 org.apache.commons.lang.ArrayUtils 包中的 contains 方法。

检查值是否在给定的数组中。

如果传入一个空数组,该方法返回false。

参数: array 要搜索的数组 valueToFind 要查找的值 回报: 如果数组包含对象,则为 true

long [] imageHashes= {12l,13l,14l,15l}; System.out.println(ArrayUtils.contains(imageHashes, 13l));

【讨论】:

  • 没有数组,都是ArrayLists。
  • 请在下次Nitin的解释中添加详细信息。这对 OP 并没有真正的帮助
  • org.apache.commons.lang.ArrayUtils 检查值是否在给定的数组中。如果传入一个空数组,则此方法返回false。 参数:array 要搜索的数组 valueToFind 要查找的值 返回:如果数组包含对象,则为true
【解决方案2】:

请问我该如何解决。我想使用 contains() 来查找 具有匹配序列号的特定对象。

在这种情况下,覆盖 Watch 的 equals() 以使用 serialNumber 字段进行比较。

然后添加接受序列号的构造函数。

public class Watch {
    private final long serialNumber;

    public Watch(long serialNumber) {
        this.serialNumber = serialNumber;
    }

    @Override
    public boolean equals(Object obj) {
        return obj == this ||
            (obj instanceof Watch && ((Watch)obj).serialNumber == serialNumber);
    }

    @Override
    public int hashCode() {
        return (int)serialNumber;
    }
}

if(watchStore.contains(s)){ 替换为if(watchStore.contains(watchToFind)){,其中Watch watchToFind = new Watch(s);

【讨论】:

  • 您在任何时候想要搜索集合时都在创建一个新实例。虽然这并没有很大的计算成本潜力,但它是违反直觉的。如果您需要查找多个字段,那么您现在必须在两个地方而不是一个地方更新您的代码。
【解决方案3】:

假设Watch 是类,watchStoreList&lt;Watch&gt;,并且serialNo 存在字段Watch...

public Optional<Watch> findWatchBySerialNumber(long serial) {
    return watchStore.stream()
                     .filter(w -> w.getSerialNo() == serial)
                     .findFirst();
}

如果您没有使用 Java 8,则代码很接近,但有点危险,因为您有机会返回 null。如果你可以使用 Guava 的Optional,这里会是更好的选择。

public Watch findWatchBySerialNumber(long serial) {
    for(Watch w : watchStore) {
        if(w.getSerialNo() == serial) {
            return w;
        }
     }
     return null;
}

您的contains 不起作用,因为您的列表不包含Longs,它包含Watchs。这也是编译器认为它可疑的原因。 contains 接受 Object,但如果您要查找的内容与列表中的内容没有可比的 equals,它将返回 false

在这种情况下,您必须遍历整个集合才能找到它,尤其是因为您正在寻找这些对象的特定属性,而不是特定的、易于提供的值。

【讨论】:

  • 您好 Makoto,如果找不到对象,Java 8 示例中的代码会返回什么?我猜也是空的?
  • 不,它返回Optional 的实例。您必须调用可选项来获取值或采取一些默认操作。 Take a look!
  • 已编译的代码但未返回包含该“序列号”的对象。因为我尝试打印出对象但没有打印任何内容。为什么?
  • @Nabstar:你确定你已经覆盖了该对象的默认 toString() 方法吗?
  • 是的,它被覆盖了......但我没有使用它来打印出具有匹配“序列号”的对象。我只是在findWatchBySerialNumber(long serial) 返回对象时使用System.out.print() 打印它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 2018-03-27
  • 2015-03-25
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
相关资源
最近更新 更多