为什么自定义实例的ArrayList上的.contains方法有效?

时间:2017-06-14 15:14:30

标签: java arraylist

我一直在开发一个小型的工作应用程序,我遇到了一些我无法弄清楚的事情。

在下面的代码中,我有一个名为“Product”的Custom Class的ArrayList,它包含“String”类型的数据。我在此ArrayList上使用.contains方法,以确保它不包含某个String。

我的IDE向我发出警告:'对java.util.Collections.contains的可疑调用:给定对象不能包含String的实例(期望的产品)'。

我完全理解上面的消息,因为我正在比较两种不同的类型,那么它如何才能正确评估呢?我认为它必须是因为'Product'类包含我想要比较的数据,它默认使用Product类上的toString方法(我在Class中重写它)并将它与我想要的String进行比较比较它。

对我来说,这似乎是JVM的黑魔法。

private void createOrderListing(List<String[]> orderList)
{
    //For each line of the order list file
    for(String[] s : orderList)
    {
        if(s.length >= 28) //OrderLine should be of this length
        {
            if (!s[0].equalsIgnoreCase("ProductCode") && !s[0].isEmpty()) //Makes sure we're not including headers
            {
                //How does this bit work?
                if(!productListing.contains(s[0]))
                {
                    OrderLine order = new OrderLine();
                    //References product code of Product against Order Line, if match, then pack sizes and other basic fields ammended as appropriate
                    boolean productFound = false;
                    for (Product p : productListing) 
                    {
                        if (s[0].contentEquals(p.getProductCode())) 
                        {
                            order.initialAmendOrderLine(p.getProductCode(), p.getProductName(), p.getPackSize(), p.getProductType());
                            productFound = true;
                        }
                    }
                    if(productFound)
                    {
                        order.setOrderValues(s);
                        orderListing.add(order);
                    }
                }
                //System.out.println("\nOrder Product is: " + order.getProductName()+ "\nOrder Pack Size is: " + order.getInternalPackSize());
            }
        }
    }
}

更新

这在注释中指出的原因是块总是为真(.contains方法总是假的,!反转它,因此是真的)。对不起因为混乱并指出了我的疏忽。

3 个答案:

答案 0 :(得分:0)

productListingProduct个对象的列表。但是,如果列表包含特定的String对象,那么您就会询问该列表 - 不应该

您应该检查的是Product#getProductCode是否等于您的特定String。这可以通过使用http://mongoc.org/libmongoc/current/authentication.html

来实现
if(!productListing.contains(s[0])) // replace this 

 // with this
if (!productListing.stream().filter(o -> o.getProductCode().equals(s[0])).findFirst().isPresent())

这段代码有什么作用?它会检查您的所有Product元素,以找到myStringData属性等于您正在比较的String的元素。

答案 1 :(得分:0)

以下是我在OpenJDK中contains中的ArrayList方法的实现:

public boolean contains(Object o) {
    return indexOf(o) >= 0;
}
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

基本上,它没有什么复杂的。它遍历ArrayList的所有元素,并检查您的给定对象是否等于当前对象。如果条件为真,则元素存在于列表中。

因此,让我们假设您将String“SomeValue”传递给此方法。迭代ArrayList的元素并执行以下操作:"SomeValue".equals(elementData[i])其中elementData[i]是产品。

由于String类的equals方法无法将String与Product进行比较,因此返回false,因此从contains方法得到错误。

要解决这种情况,您可以手动迭代ArrayList并将某个Product的字段与您的字符串进行比较。例如。你可以实现以下包含方法:

public boolean contains(List<Product> products, String yourStringValue) {
    for (Product p : products) {
        if(p.getProductCode().equals(yourStringValue)){
             return true;
        }
    }
    return false;    
}

答案 2 :(得分:-1)

因为当你执行

时包含equals实现的中继
 if(!productListing.contains(s[0]))

如果字符串包含字符串,则询问字符串列表。

将返回始终为false,因为类型不同,所以这根本不起作用,是你的条件总是返回false