当前位置: 首页 > 知识库问答 >
问题:

Java 8流列表映射与条件分组

姬俊能
2023-03-14

下课:

public class Foo {
    private Date date;
    private String name;
    private Long number;
}

我现在有一个列表 ,我想将其转换为map > (long应该是数字)的总和。使这变得困难的是,我想在内部映射中正好有26个条目,其中第26个被称为“其他”,它总结了所有数字低于其他25个的条目。

我得到了以下代码

data.stream().collect(Collectors.groupingBy(e -> e.getDate(), Collectors.groupingBy(e -> {
    if (/*get current size of inner map*/>= 25) {
        return e.getName();
    } else {
        return "Other";
    }

}, Collectors.summingLong(e -> e.getNumber()))));
Map<Date, Map<String, Long>> result = new LinkedHashMap<Date, Map<String, Long>>();
for (Foo fr : data) {
    if (result.get(fr.getDate()) == null) {
        result.put(fr.getDate(), new LinkedHashMap<String, Long>());
    }
    if (result.get(fr.getDate()) != null) {
        if (result.get(fr.getDate()).size() >= 25) {
            if (result.get(fr.getDate()).get("Other") == null) {
                result.get(fr.getDate()).put("Other", 0l);
            }
            if (result.get(fr.getDate()).get("Other") != null) {
                long numbers= result.get(fr.getDate()).get("Other");
                result.get(fr.getDate()).replace("Other", numbers+ fr.getNumbers());
            }
        } else {
            result.get(fr.getDate()).put(fr.getName(), fr.getNumbers());
        }
    }
}

共有1个答案

甘兴学
2023-03-14

我不认为这个操作会从使用流API中受益。不过,您可以使用Java ;8个特性来改进操作:

Map<Date, Map<String, Long>> result = new LinkedHashMap<>();
for(Foo fr : data) {
    Map<String, Long> inner
      = result.computeIfAbsent(fr.getDate(), date -> new LinkedHashMap<>());
    inner.merge(inner.size()>=25?"Other":fr.getAirlineName(), fr.getNumbers(), Long::sum);
}

代码假定每个日期的航空公司名称都是唯一的。否则,必须将代码扩展到

Map<Date, Map<String, Long>> result = new LinkedHashMap<>();
for(Foo fr : data) {
    Map<String, Long> inner
      = result.computeIfAbsent(fr.getDate(), date -> new LinkedHashMap<>());
    inner.merge(inner.size() >= 25 && !inner.containsKey(fr.getAirlineName())?
      "Other": fr.getAirlineName(), fr.getNumbers(), Long::sum);
}

正确累积航空公司的值。

public static <T,K,V> Collector<T,?,Map<K,V>> toMapWithLimit(
    Function<? super T, ? extends K> key, Function<? super T, ? extends V> value,
    int limit, K fallBack, BinaryOperator<V> merger) {

    return Collector.of(LinkedHashMap::new, (map, t) ->
            mergeWithLimit(map, key.apply(t), value.apply(t), limit, fallBack, merger),
            (map1,map2) -> {
                if(map1.isEmpty()) return map2;
                if(map1.size()+map2.size() < limit)
                    map2.forEach((k,v) -> map1.merge(k, v, merger));
                else
                    map2.forEach((k,v) ->
                        mergeWithLimit(map1, k, v, limit, fallBack, merger));
                return map1;
            });
}
private static <T,K,V> void mergeWithLimit(Map<K,V> map, K key, V value,
    int limit, K fallBack, BinaryOperator<V> merger) {
    map.merge(map.size() >= limit && !map.containsKey(key)? fallBack: key, value, merger);
}
Map<Date, Map<String, Long>> result = data.stream().collect(
    Collectors.groupingBy(Foo::getDate, LinkedHashMap::new,
        toMapWithLimit(Foo::getAirlineName, Foo::getNumbers, 25, "Other", Long::sum)));
 类似资料:
  • 我有一个订单列表,我想使用Java8Stream和Collectors按用户分组。GroupingBy: 这将返回包含用户和订单列表的映射: 我不需要整个对象User,只需要它的username字段,它是一个字符串,所以我想获得如下内容: 我试图使用stream.map将用户映射到username字段,但无法正确实现。我怎样才能尽可能简单地做到这一点呢?

  • 我在迭代一个对象内的列表时遇到了一个问题,该对象内嵌在另一个映射中。我的目标是迭代这个列表并生成一个映射 ,我希望使用streams和lamdas来实现这一点。 我在上面看到了,我需要通过迭代FolderBo中的elementList从elementBo创建一个带有map 的映射。folderBo本身就在Modelbo的地图内。

  • 我有以下两门课: : : 我希望进行流操作,以便: 将映射到中的 的和分别合并到和中,对于所有具有相同id的s 为此,我编写了以下一段代码: 它的工作和输出如下: 但我相信有一种更好的方式可以达到同样的效果。任何一个指针都很好。

  • 问题内容: 我有一个带有以下签名的类: 我想要一个来自a 的键,该键将是该类的名称。我如何使用java8流按es名称对列表进行分组?所有es在名称上都是唯一的。 可以在单个流中求解,还是应该以某种方式拆分它还是采用经典解决方案? 问题答案:

  • 我有映射键作为字符串和值作为列表。列表可以有10个唯一值。我需要转换这个映射键为整数和值为列表。示例如下: 输入: 2:“钥匙-1”,“钥匙-2” 3:“钥匙-1”、“钥匙-2”、“钥匙-3” 4:“钥匙-1”、“钥匙-2”、“钥匙-3”

  • 给定以下类的,使用Java 8 lambda,我希望获得的,每个帐户类型一个。 到目前为止,我使用以下代码按对进行分组。 如何返回,将列表从每个映射键传递到构造函数中,其中包含每个中的一个?