JavaでHashMapを並べ替える
1. 序章
このクイックチュートリアルでは、JavaでHashMapをソートする方法を学習します。
具体的には、 HashMap エントリを、次のコマンドを使用してキーまたは値で並べ替えることを検討します。
- TreeMap
- ArrayListおよびCollections.sort()
- TreeSet
- StreamAPIの使用
- Guavaライブラリの使用
2. TreeMapを使用する
ご存知のとおり、TreeMapのキーは、自然な順序を使用して並べ替えられます。 これは、キーと値のペアをキーで並べ替える場合に適したソリューションです。 したがって、アイデアは、すべてのデータをHashMapからTreeMapにプッシュすることです。
まず、 HashMap を定義し、いくつかのデータで初期化します。
Map<String, Employee> map = new HashMap<>();
Employee employee1 = new Employee(1L, "Mher");
map.put(employee1.getName(), employee1);
Employee employee2 = new Employee(22L, "Annie");
map.put(employee2.getName(), employee2);
Employee employee3 = new Employee(8L, "John");
map.put(employee3.getName(), employee3);
Employee employee4 = new Employee(2L, "George");
map.put(employee4.getName(), employee4);
Employee クラスの場合、 Comparable:を実装したことに注意してください。
public class Employee implements Comparable<Employee> {
private Long id;
private String name;
// constructor, getters, setters
// override equals and hashCode
@Override
public int compareTo(Employee employee) {
return (int)(this.id - employee.getId());
}
}
次に、コンストラクターを使用して、エントリをTreeMapに格納します。
TreeMap<String, Employee> sorted = new TreeMap<>(map);
putAllメソッドを使用してデータをコピーすることもできます。
TreeMap<String, Employee> sorted = new TreeMap<>();
sorted.putAll(map);
以上です! マップエントリがキーでソートされていることを確認するために、それらを印刷してみましょう。
Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}
ご覧のとおり、キーは自然な順序で並べ替えられています。
3. 使用する 配列リスト
もちろん、ArrayListを使用してマップのエントリを並べ替えることができます。 以前の方法との主な違いは、ここではマップインターフェイスを維持しないことです。
3.1. キーで並べ替え
キーセットをArrayListにロードしましょう。
List<String> employeeByKey = new ArrayList<>(map.keySet());
Collections.sort(employeeByKey);
そして、出力は次のとおりです。
[Annie, George, John, Mher]
3.2. 値で並べ替え
ここで、Employeeオブジェクトのidフィールドでマップ値を並べ替える場合はどうでしょうか。 そのためにもArrayListを使用できます。
まず、値をリストにコピーしましょう。
List<Employee> employeeById = new ArrayList<>(map.values());
次に、それを並べ替えます。
Collections.sort(employeeById);
EmployeeがComparableインターフェイスを実装しているため、これが機能することを忘れないでください。 それ以外の場合は、Collections.sortを呼び出すための手動コンパレータを定義する必要があります。
結果を確認するために、employeeByIdを出力します。
[Employee{id=1, name='Mher'},
Employee{id=2, name='George'},
Employee{id=8, name='John'},
Employee{id=22, name='Annie'}]
ご覧のとおり、オブジェクトはidフィールドで並べ替えられています。
4. TreeSetを使用する
ソートされたコレクションで重複する値を受け入れたくない場合は、TreeSetを使用した優れたソリューションがあります。
まず、最初のマップにいくつかの重複するエントリを追加しましょう。
Employee employee5 = new Employee(1L, "Mher");
map.put(employee5.getName(), employee5);
Employee employee6 = new Employee(22L, "Annie");
map.put(employee6.getName(), employee6);
4.1. キーで並べ替え
キーエントリでマップを並べ替えるには:
SortedSet<String> keySet = new TreeSet<>(map.keySet());
keySet を印刷して、出力を見てみましょう。
[Annie, George, John, Mher]
これで、マップキーが重複せずに並べ替えられました。
4.2. 値で並べ替え
同様に、マップ値の場合、変換コードは次のようになります。
SortedSet<Employee> values = new TreeSet<>(map.values());
そして結果は次のとおりです。
[Employee{id=1, name='Mher'},
Employee{id=2, name='George'},
Employee{id=8, name='John'},
Employee{id=22, name='Annie'}]
ご覧のとおり、出力に重複はありません。 これは、equalsとhashCodeをオーバーライドするときにカスタムオブジェクトで機能します。
5. ラムダとストリームの使用
Java 8以降、StreamAPIとラムダ式を使用してマップを並べ替えることができます。 必要なのは、マップのストリームパイプライン上でsortedメソッドを呼び出すことだけです。
5.1. キーで並べ替え
キーで並べ替えるには、compareByKeyコンパレータを使用します。
map.entrySet()
.stream()
.sorted(Map.Entry.<String, Employee>comparingByKey())
.forEach(System.out::println);
最後のforEachステージは、結果を出力します。
Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}
デフォルトでは、並べ替えモードは昇順です。
5.2. 値で並べ替え
もちろん、Employeeオブジェクトで並べ替えることもできます。
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.forEach(System.out::println);
ご覧のとおり、上記のコードは、Employeeオブジェクトのidフィールドでソートされたマップを出力します。
Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}
さらに、結果を新しいマップに収集できます。
Map<String, Employee> result = map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
結果をLinkedHashMapに収集したことに注意してください。デフォルトでは、 Collectors.toMap は新しいHashMapを返しますが、ご存知のとおり、HashMapは反復を保証しません order 、、LinkedHashMapはそうです。
6. グアバの使用
最後に、HashMapをソートできるライブラリはGuavaです。 始める前に、Guavaのマップに関する記事を確認すると便利です。
まず、従業員の Id フィールドでマップを並べ替えたいので、Orderingを宣言しましょう。
Ordering naturalOrdering = Ordering.natural()
.onResultOf(Functions.forMap(map, null));
ここで必要なのは、ImmutableSortedMapを使用して結果を説明することだけです。
ImmutableSortedMap.copyOf(map, naturalOrdering);
また、出力はidフィールド順に並べられたマップです。
Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}
7. 概要
この記事では、HashMapをキーまたは値で並べ替えるいくつかの方法を確認しました。
また、属性がカスタムクラスの場合に、Compareableを実装することでこれを行う方法を学びました。
最後に、いつものように、この記事で使用されているコードは、GitHubのにあります。