流分组:减少到列表的第一个元素

Fab*_* B. 25 java grouping java-8 java-stream collectors

我有一个List<Valuta>可以表示(简化)JSON风格:

[{codice = EUR,description = Euro,ratio = 1},{codice = USD,description = Dollars,ratio = 1.1}]

我想用这样的方式改变它Map<String, Valuta>:

{EUR = {codice = EUR,description = Euro,ratio = 1},USD = {codice = USD,description = Dollars,ratio = 1.1}}

我写了这个单行:

getValute().stream().collect(Collectors.groupingBy(Valuta::getCodice));
Run Code Online (Sandbox Code Playgroud)

但这会返回一个Map<String, List<Valuta>>而不是我需要的东西.

我认为mapping()功能对我有用,但不知道如何.

Tun*_*aki 35

实际上,你需要在Collectors.toMap这里使用而不是Collectors.groupingBy:

Map<String, Valuta> map = 
    getValute().stream()
               .collect(Collectors.toMap(Valuta::getCodice, Function.identity()));
Run Code Online (Sandbox Code Playgroud)

groupingBy用于根据分组功能对Stream的元素进行分组.2 List默认情况下,将与分组功能具有相同结果的流元素收集到a中.

toMap将元素收集到Map键是应用给定键映射器的结果的位置,值是应用值映射器的结果.请注意toMap,默认情况下,如果遇到重复,则会抛出异常.

  • 怎样对`groupingBy`做同样的事情?我不能使用`toMap`,因为我必须期待键映射器中重复的键。我看到`groupingBy`具有下游收集器的签名作为第二个参数,但是还不能使它起作用。 (2认同)

Phi*_*ppe 17

这场比赛有点晚了,但试试这个:

Map<String, Valuta> map = 
    getValute().stream()
               .collect(Collectors.groupingBy(Valuta::getCodice,
                            Collectors.collectingAndThen(
                                Collectors.toList(), 
                                values -> values.get(0))));
Run Code Online (Sandbox Code Playgroud)

  • 为什么要在流中创建列表?这里您的解决方案在不创建列表的情况下进行了调整:`getValute().stream().collect(groupingBy(Valuta::getCodice,ducing(null,identity(),(first,last) -&gt; last)))` (4认同)
  • 如果您确实有重复项,但又不想使用它,这就是需要的 (2认同)
  • 您也许可以使用“.toMap”的“mergeFunction”来简单地删除任何重复项并避免额外的对象分配:/sf/answers/2261914861/ (2认同)

Psh*_*emo 11

你可以用 Collectors.toMap(keyMappingFunction, valueMappingFunction)

Map<String, Valuta> map = list
        .stream()
        .collect(Collectors.toMap(Valuta::getCodice, v -> v));
Run Code Online (Sandbox Code Playgroud)

如果您发现它更具可读性v->v,Function.identity()则可以替换.


小智 6

toMap其中选择只选择在碰撞第一个值,而不是抛出一个异常的版本:

Collectors.toMap(keyMapper, valueMapper, mergeFunction) 前任:

Map<String, Valuta> map = list
        .stream()
        .collect(Collectors.toMap(Valuta::getCodice, v -> v, (v1, v2) -> v1));
Run Code Online (Sandbox Code Playgroud)