基於流建立地圖

簡單的情況沒有重複的鍵

Stream<String> characters = Stream.of("A", "B", "C");

Map<Integer, String> map = characters
            .collect(Collectors.toMap(element -> element.hashCode(), element -> element));
// map = {65=A, 66=B, 67=C}

為了使事情更具說明性,我們可以在 Function 介面中使用靜態方法 - Function.identity() 。我們可以用 Function.identity() 替換這個 lambda element -> element

可能存在重複鍵的情況

Collectors.toMapjavadoc 宣告:

如果對映的鍵包含重複項(根據 Object.equals(Object)),則在執行收集操作時會丟擲 IllegalStateException。如果對映的鍵可能有重複,請改用 toMap(Function, Function, BinaryOperator)

Stream<String> characters = Stream.of("A", "B", "B", "C");

Map<Integer, String> map = characters
            .collect(Collectors.toMap(
                element -> element.hashCode(),
                element -> element,
                (existingVal, newVal) -> (existingVal + newVal)));

// map = {65=A, 66=BB, 67=C}

傳遞給 Collectors.toMap(...)BinaryOperator 生成在碰撞情況下儲存的值。它可以:

  • 返回舊值,以便流中的第一個值優先,
  • 返回新值,以便流中的最後一個值優先,或
  • 結合新舊值

按價值分組

當你需要執行等效的資料庫級聯分組依據操作時,可以使用 Collectors.groupingBy 。為了說明,下面建立了一個地圖,其中人們的姓名被對映到姓氏:

List<Person> people = Arrays.asList(
    new Person("Sam", "Rossi"),
    new Person("Sam", "Verdi"),
    new Person("John", "Bianchi"),
    new Person("John", "Rossi"),
    new Person("John", "Verdi")
);

Map<String, List<String>> map = people.stream()
        .collect(
                // function mapping input elements to keys
                Collectors.groupingBy(Person::getName, 
                // function mapping input elements to values,
                // how to store values
                Collectors.mapping(Person::getSurname, Collectors.toList()))
        );

// map = {John=[Bianchi, Rossi, Verdi], Sam=[Rossi, Verdi]}

住在 Ideone 上