にArrayList
多数のレコードがあり、1つの列にCO2 CH4 SO2などのガス名が含まれていArrayList
ます。ここで、から繰り返さずに、異なるガス名(一意)のみを取得したいと思います。どうすればそれができますか?
回答:
を使用する必要があり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()メソッドを呼び出すことによって重複を識別します。
java: no suitable constructor found for HashSet
。なぜこれが発生するのか考えていますか?
LinkedHashSet
stackoverflow.com
メソッド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
私はあなたの質問を正しく理解することを願っています:値がタイプString
であると仮定すると、最も効率的な方法はおそらくに変換してHashSet
それを反復することです:
ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
... //Do something
}
ArrayList values = ... // your values
Set uniqueValues = new HashSet(values); //now unique
カスタムコンパレータやそのようなものに頼ることなく、簡単な方法があります:
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
、ソートが必要な場合でも使用する方が良い場合が多く、悪い場合はほとんどありません。
同じクエリを実行していたとき、以前のすべての回答には優れた洞察がありましたが、自分のケースに合わせてソリューションを調整するのに苦労しました。
これは、文字列ではなく、一意のオブジェクトのリストを取得する必要がある場合の解決策です。たとえば、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
。
ここで、レコードのリストはallRecord
(List<Record> allRecord
)であるとしましょう。
Set<Record> distinctRecords = new HashSet<>();
for(Record rc: allRecord){
distinctRecords.add(rc);
}
これにより、個別のレコードがハッシュセットの個別レコードにのみ追加されます。
お役に立てれば。
ある種のオブジェクト(bean)の配列がある場合は、次のようにすることができます。
List<aBean> gasList = createDuplicateGasBeans();
Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
等は上記のマティアス・シュワルツを言っていますが、メソッドを使用してaBeanを提供する必要がありhashCode()
かつequals(Object obj)
それが専用メニュー「でのEclipseで簡単に行うことができるGenerate hashCode() and equals()
」(Beanクラスにいる間)。Setは、オーバーライドされたメソッドを評価して、等しいオブジェクトを識別します。