Java 8 Stream Collectors – 用于在多个存储桶中创建包含对象的Map的收集器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java 8 Stream Collectors – 用于在多个存储桶中创建包含对象的Map的收集器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2891字,纯文字阅读大概需要5分钟。
内容图文
![Java 8 Stream Collectors – 用于在多个存储桶中创建包含对象的Map的收集器](/upload/InfoBanner/zyjiaocheng/727/4d84d95f3d1445d3850b2bee6ec65ab0.jpg)
以下代码有效并且可读,但在我看来,我有中间操作,感觉它们不应该是必需的.我写了这个简化版本,因为实际代码是一个更大的过程的一部分.
我有一个Widget集合,每个都有一个名称和多个类型(由WidgetType枚举的常量表示).这些多种类型可以作为Stream< WidgetType>获取.但是,如果有必要,我可以将其作为其他类型返回. (由于各种原因,强烈希望将它们作为Stream< WidgetType>返回,因为这些小部件将在以后的实际代码中使用.)
这些小部件被添加到EnumMap< WidgetType,List< Widget>>稍后,将其翻译成EnumMap< WidgetType,Widget []>.
如果每个Widget只有一个WidgetType,这将是一个简单的解决,但是,因为任何Widget可能有一个或多个类型,我使用Collectors.groupingBy()方法(及其重载)的语法绊倒我自己.
这里的代码示例再次完全正常,并给出了我需要的确切结果.
class StackOverFlowExample {
private final Map<WidgetType, Widget[]> widgetMap = new EnumMap<>(WidgetType.class);
public static void main(String[] args) { new StackOverFlowExample(); }
StackOverFlowExample() {
Collection<Widget> widgetList = getWidgetsFromWhereverWidgetsComeFrom();
{
final Map<WidgetType, List<Widget>> intermediateMap = new EnumMap<>(WidgetType.class);
widgetList.forEach(w ->
w.getWidgetTypes().forEach(wt -> {
intermediateMap.putIfAbsent(wt, new ArrayList<>());
intermediateMap.get(wt).add(w);
})
);
intermediateMap.entrySet().forEach(e -> widgetMap.put(e.getKey(), e.getValue().toArray(new Widget[0])));
}
Arrays.stream(WidgetType.values()).forEach(wt -> System.out.println(wt + ": " + Arrays.toString(widgetMap.get(wt))));
}
private Collection<Widget> getWidgetsFromWhereverWidgetsComeFrom() {
return Arrays.asList(
new Widget("1st", WidgetType.TYPE_A, WidgetType.TYPE_B),
new Widget("2nd", WidgetType.TYPE_A, WidgetType.TYPE_C),
new Widget("3rd", WidgetType.TYPE_A, WidgetType.TYPE_D),
new Widget("4th", WidgetType.TYPE_C, WidgetType.TYPE_D)
);
}
}
这输出:
TYPE_A: [1st, 2nd, 3rd]
TYPE_B: [1st]
TYPE_C: [2nd, 4th]
TYPE_D: [3rd, 4th]
为了完整起见,这里是Widget类和WidgetType枚举:
class Widget {
private final String name;
private final WidgetType[] widgetTypes;
Widget(String n, WidgetType ... wt) { name = n; widgetTypes = wt; }
public String getName() { return name; }
public Stream<WidgetType> getWidgetTypes() { return Arrays.stream(widgetTypes).distinct(); }
@Override public String toString() { return name; }
}
enum WidgetType { TYPE_A, TYPE_B, TYPE_C, TYPE_D }
关于更好地执行此逻辑的任何想法都是受欢迎的.谢谢!
解决方法:
恕我直言,关键是将Widget实例转换为Stream< Pair< WidgetType,Widget>>实例.一旦我们有了这个,我们可以平面映射一个小部件流并收集生成的流.当然我们在Java中没有Pair,所以必须使用AbstractMap.SimpleEntry.
widgets.stream()
// Convert a stream of widgets to a stream of (type, widget)
.flatMap(w -> w.getTypes().map(t->new AbstractMap.SimpleEntry<>(t, w)))
// Grouping by the key, and do additional mapping to get the widget
.collect(groupingBy(e->e.getKey(),
mapping(e->e.getValue,
collectingAndThen(toList(), l->l.toArray(new Widget[0])))));
附:在这种情况下,IntelliJ的建议不会缩短带方法参考的lambda.
内容总结
以上是互联网集市为您收集整理的Java 8 Stream Collectors – 用于在多个存储桶中创建包含对象的Map的收集器全部内容,希望文章能够帮你解决Java 8 Stream Collectors – 用于在多个存储桶中创建包含对象的Map的收集器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。