Javaのarraylistから一意の値を取得します


83

ArrayList多数のレコードがあり、1つの列にCO2 CH4 SO2などのガス名が含まれていArrayListます。ここで、から繰り返さずに、異なるガス名(一意)のみを取得したいと思います。どうすればそれができますか?


4
タグを更新します。これはJavaの質問であり、jsfやprimefacesとは無関係だと思います...–
Mathias Schwarz

回答:


136

を使用する必要がありSetます。ASetは、重複を含まないコレクションです。

List重複を含むがある場合は、次のような一意のエントリを取得できます。

List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());

:このHashSetコンストラクターは、要素のequals()メソッドを呼び出すことによって重複を識別します。


これは、名前が等しい場合、2つのレコードが(HashSetの意味で)等しいと見なされることを意味します。
njzk2 2014年

@ njzk2-それはかなり明白だと思いましたが、編集して明示的に指摘できると思います...
jahroy 2014年

上記のコードを実装しようとするとエラーが発生します: java: no suitable constructor found for HashSet。なぜこれが発生するのか考えていますか?
lordlabakdas 2017

リストから元の注文を保持したい場合は、LinkedHashSet stackoverflow.com
a / 8712770/32453 –rogerdpack20年

68

Java 8 StreamAPIを使用できます

メソッドdistinctは、ストリームをフィルタリングし、(デフォルトではObject :: equalsメソッドを使用して)個別の値のみが次の操作に渡されるようにする中間操作です。
私はあなたのケースのために以下の例を書きました、

// Create the list with duplicates.
List<String> listAll = Arrays.asList("CO2", "CH4", "SO2", "CO2", "CH4", "SO2", "CO2", "CH4", "SO2");

// Create a list with the distinct elements using stream.
List<String> listDistinct = listAll.stream().distinct().collect(Collectors.toList());

// Display them to terminal using stream::collect with a build in Collector.
String collectAll = listAll.stream().collect(Collectors.joining(", "));
System.out.println(collectAll); //=> CO2, CH4, SO2, CO2, CH4 etc..
String collectDistinct = listDistinct.stream().collect(Collectors.joining(", "));
System.out.println(collectDistinct); //=> CO2, CH4, SO2

12

私はあなたの質問を正しく理解することを願っています:値がタイプStringであると仮定すると、最も効率的な方法はおそらくに変換してHashSetそれを反復することです:

ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
   ... //Do something
}

6
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique

リストから一意の要素を取得していますが、それ自体が並べ替えられていますが、データが並べ替えられていない必要があります。どうすればよいですか?
SDas 2012年

6

カスタムコンパレータやそのようなものに頼ることなく、簡単な方法があります:

Set<String> gasNames = new HashSet<String>();
List<YourRecord> records = ...;

for(YourRecord record : records) {
  gasNames.add(record.getGasName());
}

// now gasNames is a set of unique gas names, which you could operate on:
List<String> sortedGasses = new ArrayList<String>(gasNames);
Collections.sort(sortedGasses);

注:TreeSet代わりにHashSetを使用すると、直接ソートされたarraylistが得られ、上記Collections.sortはスキップできますが、TreeSetそれ以外の場合は効率が低下するためHashSet、ソートが必要な場合でも使用する方が良い場合が多く、悪い場合はほとんどありません。


3

これを使用してリストを一意にすることができます

ArrayList<String> listWithDuplicateValues = new ArrayList<>();
list.add("first");
list.add("first");
list.add("second");

ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());

2

同じクエリを実行していたとき、以前のすべての回答には優れた洞察がありましたが、自分のケースに合わせてソリューションを調整するのに苦労しました。

これは、文字列ではなく、一意のオブジェクトのリストを取得する必要がある場合の解決策です。たとえば、Recordオブジェクトのリストがあるとします。Recordこのクラスは、型のプロパティのみ持ってString、タイプのNOプロパティをint。ここでは、を返す必要hashCode()があるため、実装が困難になりhashCode()ますint

以下はサンプルRecordクラスです。

public class Record{

    String employeeName;
    String employeeGroup;

    Record(String name, String group){  
        employeeName= name;
        employeeGroup = group;    
    }
    public String getEmployeeName(){
        return employeeName;
    }
    public String getEmployeeGroup(){
        return employeeGroup;
    }

  @Override
    public boolean equals(Object o){
         if(o instanceof Record){
            if (((Record) o).employeeGroup.equals(employeeGroup) &&
                  ((Record) o).employeeName.equals(employeeName)){
                return true;
            }
         }
         return false;
    }

    @Override
    public int hashCode() { //this should return a unique code
        int hash = 3; //this could be anything, but I would chose a prime(e.g. 5, 7, 11 )
        //again, the multiplier could be anything like 59,79,89, any prime
        hash = 89 * hash + Objects.hashCode(this.employeeGroup); 
        return hash;
    }

以前他の人によって示唆されるように、クラスのニーズは両方上書きするequals()hashCode()使用できるようにする方法をHashSet

ここで、レコードのリストはallRecordList<Record> allRecord)であるとしましょう。

Set<Record> distinctRecords = new HashSet<>();

for(Record rc: allRecord){
    distinctRecords.add(rc);
}

これにより、個別のレコードがハッシュセットの個別レコードにのみ追加されます。

お役に立てれば。


2
    public static List getUniqueValues(List input) {
      return new ArrayList<>(new LinkedHashSet<>(incoming));
    }

最初にequalsメソッドを実装することを忘れないでください


1

ある種のオブジェクト(bean)の配列がある場合は、次のようにすることができます。

List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);

等は上記のマティアス・シュワルツを言っていますが、メソッドを使用してaBeanを提供する必要がありhashCode()かつequals(Object obj)それが専用メニュー「でのEclipseで簡単に行うことができるGenerate hashCode() and equals()」(Beanクラスにいる間)。Setは、オーバーライドされたメソッドを評価して、等しいオブジェクトを識別します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.