web-dev-qa-db-ja.com

ArrayListから重複した値を削除する

文字列のArraylistが1つあり、その中に重複値をいくつか追加しました。そして、私はちょうどその重複値を削除したいので、それを削除する方法。

ここで例私は一つのアイデアを得ました。

List<String> list = new ArrayList<String>();
        list.add("Krishna");
        list.add("Krishna");
        list.add("Kishan");
        list.add("Krishn");
        list.add("Aryan");
        list.add("Harm");

        System.out.println("List"+list);

        for (int i = 1; i < list.size(); i++) {
            String a1 = list.get(i);
            String a2 = list.get(i-1);
            if (a1.equals(a2)) {
                list.remove(a1);
            }
        }

        System.out.println("List after short"+list);

しかし、その重複フォームリストを削除するのに十分な方法はありますか。 Forループを使用せずに?そして、私はHashSetまたは他の方法を使用してそれを行うことができますが、配列リストのみを使用します。そのための提案をしたいと思います。事前にお答えいただきありがとうございます。

18
Krishna

リストからLinkedHashSetを作成できます。 LinkedHashSetには、Listと同じ順序で各要素が1回だけ含まれます。次に、このListから新しいLinkedHashSetを作成します。事実上、それはワンライナーです:

list = new ArrayList<String>(new LinkedHashSet<String>(list))

List#containsまたはList#removeを含むアプローチは、おそらく漸近的な実行時間をO(n)(上記の例))からO(n ^ 2)に短縮します。 。


[〜#〜] edit [〜#〜]コメントで言及された要件の場合:重複する要素を削除したいが、文字列をequalケースを無視すると、次のようなことができます:

Set<String> toRetain = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
toRetain.addAll(list);
Set<String> set = new LinkedHashSet<String>(list);
set.retainAll(new LinkedHashSet<String>(toRetain));
list = new ArrayList<String>(set);

実行時間はO(n * logn)になりますが、これは他の多くのオプションよりも優れています。これは必要以上にやや複雑に見えることに注意してください。リスト内の要素のorderは変更できないと想定しました。リスト内の要素の順序が重要でない場合は、単純に行うことができます

Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
set.addAll(list);
list = new ArrayList<String>(set);
59
Marco13

arraylistのみを使用する場合は、パフォーマンスが大幅に向上するより良い方法はないのではないかと心配しています。しかし、arraylistを使用するだけで、次のようにリストに追加する前にチェックします

void addToList(String s){
  if(!yourList.contains(s))
       yourList.add(s);
}

この場合、セットの使用が適しています。

11
stinepike

以下に示すように、Google Guavaユーティリティを使用できます。

 list = ImmutableSet.copyOf(list).asList(); 

これはおそらく、リストから重複を削除する最も効率的な方法であり、興味深いことに、preserves反復順序も同様です。

[〜#〜] update [〜#〜]

ただし、場合によっては、グアバを使用したくない場合は、以下に示すように重複を削除できます。

ArrayList<String> list = new ArrayList<String>();
    list.add("Krishna");
    list.add("Krishna");
    list.add("Kishan");
    list.add("Krishn");
    list.add("Aryan");
    list.add("Harm");

System.out.println("List"+list);
HashSet hs = new HashSet();
hs.addAll(list);
list.clear();
list.addAll(hs);

しかし、もちろん、これはArrayListの要素の反復順序を破壊します。

ししる

9
Shishir Kumar

Java 8ストリーム関数

上記のような distinct 関数を使用して、リストの個別の要素を取得できます。

stringList.stream().distinct();

ドキュメントから、

このストリームの個別の要素(Object.equals(Object)による)で構成されるストリームを返します。


別の方法として、equalsメソッドを使用したくない場合は、次のように collect 関数を使用します。

stringList.stream()  
    .collect(Collectors.toCollection(() -> 
        new TreeSet<String>((p1, p2) -> p1.compareTo(p2)) 
));  

ドキュメントから、

Collectorを使用して、このストリームの要素に対して可変リダクション操作を実行します。

お役に立てば幸いです。

6
List<String> list = new ArrayList<String>();
        list.add("Krishna");
        list.add("Krishna");
        list.add("Kishan");
        list.add("Krishn");
        list.add("Aryan");
        list.add("Harm");

HashSet<String> hs=new HashSet<>(list);

System.out.println("=========With Duplicate Element========");
System.out.println(list);
System.out.println("=========Removed Duplicate Element========");
System.out.println(hs);
3
RaviSoni

リストから重複を削除するためのシンプルな機能

private void removeDuplicates(List<?> list)
{
    int count = list.size();

    for (int i = 0; i < count; i++) 
    {
        for (int j = i + 1; j < count; j++) 
        {
            if (list.get(i).equals(list.get(j)))
            {
                list.remove(j--);
                count--;
            }
        }
    }
}

例:
入力:[1、2、2、3、1、3、3、2、3、1、2、3、3、4、4、4、1]
出力:[1、2、3、4]

3
BRIJ
     public List<Contact> removeDuplicates(List<Contact> list) {
    // Set set1 = new LinkedHashSet(list);
    Set set = new TreeSet(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
                 if(((Contact)o1).getId().equalsIgnoreCase(((Contact)2).getId()) ) {
                return 0;
            }
            return 1;
        }
    });
    set.addAll(list);
    final List newList = new ArrayList(set);
    return newList;
}

LinkedHashsetを使用しているため(LinkedHashsetの代わりにArrayListを直接使用できます)、list = new ArrayList<String>(new LinkedHashSet<String>(list))は最良の方法ではないと思います。

解決:

import Java.util.ArrayList;
public class Arrays extends ArrayList{

@Override
public boolean add(Object e) {
    if(!contains(e)){
        return super.add(e);
    }else{
        return false;
    }
}

public static void main(String[] args) {
    Arrays element=new Arrays();
    element.add(1);
    element.add(2);
    element.add(2);
    element.add(3);

    System.out.println(element);
}
}

出力:[1、2、3]

ここでは、ArrayListメソッドをオーバーライドすることでいくつかの変更を加えて使用しているため、addを拡張しています。

2
Manojkumar
public static void main(String[] args) {
    @SuppressWarnings("serial")
    List<Object> lst = new ArrayList<Object>() {
        @Override
        public boolean add(Object e) {
            if(!contains(e))
            return super.add(e);
            else
            return false;
        }
    };
    lst.add("ABC");
    lst.add("ABC");
    lst.add("ABCD");
    lst.add("ABCD");
    lst.add("ABCE");
    System.out.println(lst);

}

これが良い方法です

1

list = list.stream().distinct().collect(Collectors.toList());
これは、Java8 Stream APIを使用したソリューションの1つです。お役に立てれば。

1
Nisarg Patil

これが最良の方法です

    List<String> list = new ArrayList<String>();
    list.add("Krishna");
    list.add("Krishna");
    list.add("Kishan");
    list.add("Krishn");
    list.add("Aryan");
    list.add("Harm");

    Set<String> set=new HashSet<>(list);

ループなしで、NoArrayListはキーではなく順序でインデックス付けされるため、リスト全体を反復処理しないとターゲット要素を見つけることができません。

プログラミングの良い習慣は、シナリオに合わせて適切なデータ構造を選択することです。したがって、Setがシナリオに最も適している場合、Listを使用して実装し、不適切なデータ構造を使用する最速の方法を見つけようとすることは意味がありません。

1
Weibo Li

HastSet を使用することをお勧めします

1-a)HashSetはオブジェクトのセットを保持しますが、オブジェクトがすでにセット内にあるかどうかを簡単かつ迅速に判断できるようにします。内部的に配列を管理し、オブジェクトのハッシュコードから計算されたインデックスを使用してオブジェクトを保存することにより、そうします。こちらをご覧ください

1-b)HashSetは、一意の要素を含む順不同のコレクションです。 Add、Remove、Containsの標準コレクション操作がありますが、ハッシュベースの実装を使用しているため、これらの操作はO(1)です。 (たとえば、Listは、ContainsとRemoveのO(n)です)。HashSetは、ユニオン、インターセクション、対称差分などの標準セット操作も提供します。こちらをご覧ください。

2)セットにはさまざまな実装があります。いくつかは、要素をハッシュすることによって挿入と検索操作を超高速にします。ただし、これは、要素が追加された順序が失われることを意味します。他の実装では、実行時間が遅くなる代わりに追加された順序が保持されます。

C#のHashSetクラスは最初のアプローチを採用しているため、要素の順序は保持されません。通常のリストよりもはるかに高速です。いくつかの基本的なベンチマークでは、プライマリタイプ(int、double、boolなど)を処理する場合、HashSetがかなり高速であることが示されました。クラスオブジェクトを操作する場合は、はるかに高速です。そのため、HashSetは高速です。

HashSetの唯一の欠点は、インデックスによるアクセスがないことです。要素にアクセスするには、列挙子を使用するか、組み込み関数を使用してHashSetをリストに変換し、それを反復処理します。

1
Furquan Khan

Java 8:

public static <T> List<T> removeDuplicates(List<T> list) {
    return list.stream().collect(Collectors.toSet()).stream().collect(Collectors.toList());
}
0
Brice Roncace
public static List<String> removeDuplicateElements(List<String> array){
    List<String> temp = new ArrayList<String>();
    List<Integer> count = new ArrayList<Integer>();
    for (int i=0; i<array.size()-2; i++){
        for (int j=i+1;j<array.size()-1;j++)
            {
                if (array.get(i).compareTo(array.get(j))==0) {
                    count.add(i);
                    int kk = i;
                }
            }
        }
        for (int i = count.size()+1;i>0;i--) {
            array.remove(i);
        }
        return array;
    }
}
0
leeyang

ArrayListのみを使用し、他のCollectionクラスを使用せずに重複を削除する必要がある場合:

//list is the original arraylist containing the duplicates as well
List<String> uniqueList = new ArrayList<String>();
    for(int i=0;i<list.size();i++) {
        if(!uniqueList.contains(list.get(i)))
            uniqueList.add(list.get(i));
    }

お役に立てれば!

0
iamharish15
private static void removeDuplicates(List<Integer> list)
{
    Collections.sort(list);
    int count = list.size();
    for (int i = 0; i < count; i++) 
    {
        if(i+1<count && list.get(i)==list.get(i+1)){
            list.remove(i);
            i--;
            count--;
        }
    }
}
0
sid