簡體   English   中英

刪除 ArrayList 中的重復項 - Java

[英]Remove duplicates in ArrayList - Java

我的 Java 代碼有問題。 我應該使用循環而不是任何其他方法。 說我的ArrayLis包含

【狗貓狗狗貓狗馬】

我的目標也是刪除 Dog 和 Cat 的副本,以便我的最終結果等於

【狗貓馬】

public void removeDouble(){

int counter = 0;
for (int i = 0 ; i < animals.size(); i++) { 
    for (int j = 1+i;  j < animals.size() ; j++)  
        //don't start on the same word or you'll eliminate it.
        if ( animals.get(j).equals( animals.get(i) )  ) {
            animals.remove(animals.get(j));
           counter++;

        }                                
    } 
}

感覺“邏輯”是正確的,但我的代碼不能很好地工作。 有人可以幫我一點嗎?

你可以這樣做。

 ArrayList<String>list=new ArrayList<>();
    list.add("A");
      list.add("B");
      list.add("C");
      list.add("A");
    System.out.println("Before "+list); // output[A,B,C,A]


    Set<String> listWithoutDuplicates = new LinkedHashSet<String>(list);
     list.clear();

    list.addAll(listWithoutDuplicates);
    System.out.println("list without duplicates : " + list);// output[A,B,C]

內循環的邏輯不正確。

每次在列表中連續出現相同的項目時,您將跳過項目。

假設你有“狗”、“狗”、“狗”、“貓”。 當您刪除索引 1 處的“狗”時,列表現在變為“狗”、“狗”、“貓”。

問題是您的“j”索引現在增加到 2,因此下一個測試將訪問“cat”項目,而不是“dog”項目。 因此,每次刪除一個項目時,您都會跳過列表中的下一個項目,這就是您得到不一致結果的原因。

解決方案是:

  1. 每次刪除項目時遞減 j 變量
  2. 從列表的末尾開始內循環,然后倒數到 0。

從列表的末尾開始並遞減計數器會更簡單。 刪除 i 處的雙精度值后,我們可以在不檢查整個字符串的情況下中斷,因為當 i 到達 j 時將檢測到進一步的雙精度值。

    for(int i=animals.size()-1; i>0; i--) {
        for(int j=i-1; j>=0; j--) {
            if(animals.get(i).equals(animals.get(j))) {
                animals.remove(i);
                break;
            }
        }
    }

向后移動可以避免在向前移動時出現問題,因為您刪除了較早的元素(並且您未能調整索引以將其考慮在內),因此索引已更改。

您使用的是 remove(object) 而不是 remove(index) 的邏輯的另一個問題,這會導致第一個匹配的對象被刪除。 但是,根據預期輸出,您希望保留第一個匹配對象的順序。 因此,您應該通過 index.html 刪除最后一個匹配的對象。


如果您想向前移動而不是向后移動,但您不想在刪除后對索引進行調整,則可以使用迭代器的 remove 方法:

    for(int i=0; i<animals.size()-1; i++) {
        ListIterator<?> iter = animals.listIterator(i+1);
        while(iter.hasNext()) {
            if(animals.get(i).equals(iter.next())) {
                iter.remove();
            }
        }
    }

不幸的是,這里的外循環不能使用迭代器,因為這會導致 ConcurrentModificationException。


最后,您還可以使用 subList 通過單個顯式循環來解決它:

    for(int i=0; i<animals.size()-1; i++) {
        animals.subList(i+1, animals.size()).removeIf(animals.get(i)::equals);
    }

在 Java 8 中,我們可以使用 Stream API 刪除重復項,如下所示。

List<String> uniqueAnimal = animal.stream().distinct().collect(Collectors.toList()); 

工作示例。

import java.util.*;
import java.util.stream.Collectors;
public class MyClass {
    public static void main(String args[]) {
        List<String> animal = new ArrayList<>();
        animal.add("Dog");
        animal.add("Cat");
        animal.add("Dog");
        animal.add("Dog");
        animal.add("Cat");
        animal.add("Dog");
        animal.add("Horse");
        List<String> uniqueAnimal = animal.stream().distinct().collect(Collectors.toList());
        System.out.println("animal =>  " + animal);
        System.out.println("uniqueAnimal =>  " + uniqueAnimal);
    }
}

使用 Java 8 流,您可以執行以下操作:

public class RemoveDuplicates {

public static void main(String[] args) {
    removeDuplicateElements(Arrays.asList("Dog","Cat","Dog","Dog","Cat","Dog","Horse"));
  }

private static void removeDuplicateElements(List<String> animalList)
  {
    animalList.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);
  }

}

您當前的代碼 -

for (int i = 0; i < animals.size(); i++) {
     for (int j = 1 + i; j < animals.size(); j++)
         if (animals.get(j).equals(animals.get(i))) {
             animals.remove(animals.get(j)); // this would remove the current element only if the previous element is same as the current element
             // since the index `j` would change post that 
         }
     }
}

一個簡單的方法是

animals.stream().distinct().collect(Collectors.toList()).forEach(System.out::print);

或使用 -

Set<String> distAnimal = new HashSet<>(animals);
System.out.println(Arrays.toString(distAnimal.toArray()));

您在迭代它們時刪除項目,有一個包含索引的數組,當您找到雙精度值時,將索引添加到索引數組中。 迭代索引數組並從動物數組列表中刪除。

感謝所有的答案。 我仍然有一些問題,這是我想出的:

    int counter =0;
for(int i = 0 ; i < animals.size() ; i++){
    for(int j = animals.size() -1 ; j>i ; j--){
        if(animals.get(j).equals(animals.get(i))){
            counter++;

}

    }
}
    System.out.println(counter);
}

所以現在我從 ArrayList 的末尾開始內部循環。 現在的優先事項只是讓循環工作,然后添加刪除等。

干杯!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM