2017-06-14 28 views
0

我一直在開發一個小型應用程序的工作,我遇到了一些我不明白的東西。爲什麼自定義實例的ArrayList上的.contains方法工作?

在下面的代碼中,我有一個名爲'Product'的Custom Class的ArrayList,其中包含'String'類型的數據。我在這個ArrayList上使用.contains方法來確保它不包含某個String。

我的IDE給了我'可疑調用java.util.Collections.contains:給定對象不能包含字符串(預期產品)'的實例'的警告。

我完全理解上面的消息,因爲我比較了兩種不同的類型,所以它如何才能正確評估?我在想這一定是因爲'Product'類包含我想要比較的數據,所以默認在Product類中使用toString方法(我在類中重寫了這個),並將其與我想要的字符串進行比較比較它。

這對我來說似乎是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()); 
      } 
     } 
    } 
} 

UPDATE

這部作品在評論中指出的原因是,該塊始終是真實的(該方法。載始終是假的,!這逆,因此,真正的)。對不起,我的粗心,並指出我的粗心。

+2

如果'Product'的equals()'方法與'String'參數相等,'contains()'方法*可以工作。它不應該在技術上違反equals()的合約,但它可以這樣做。 – Andreas

+1

哪種類型是productListing?我假設你所說的是類似於列表 sirandy

+1

productListing是類型列表 aliwaii

回答

-1

因爲包含繼電器上等於實現,當你做

if(!productListing.contains(s[0])) 

你所要求的字符串數組列表中如果包含一個字符串。

,將返回始終爲false,因爲類型不同,所以不能說是工作在所有的,是你的條件將始終返回false

+0

如果'Product.equals()'也檢查'String'參數,它將不會返回false。 – Andreas

+0

S [0]是一個字符串,而不是一個數組 –

+1

'productListing'是'名單' – matoni

0

productListingProduct對象的列表。然而,你問清單是否包含特定的String對象 - 哪個不應該曾經發生過。

您應該做的是檢查您的Product#getProductCode是否等於您的具體String。這可以通過使用streams

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

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

這段代碼是做什麼的?它會檢查您的所有Product元素以找到其myStringData屬性等於您正在比較的String的元素。

+0

也許你和我解釋了OP的問題的列表不同。您(正確)回答瞭如何解決問題;但我想他問爲什麼它已經出現了工作(我懷疑答案是OP是誤解結果)。 –

+0

@KlitosKyriacou TO在哪裏說它工作?標題中有 – Nathan

+0

。並且在對.contains()的調用之上的註釋中。 –

0

這裏是contains方法的ArrayList的實現,我在OpenJDK的:

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]是產品。

由於equals String類的方法無法將String與Product進行比較,因此返回false,因此您從contains方法中獲得false。

要解決這種情況,您可以手動迭代ArrayList,並將某個Product的字段與字符串進行比較。例如。您可以實現以下包含方法:

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