我有两个具有一对多关系的实体,它们通过复合主键连接在一起。由于Spring Data为oracle数据库生成错误计数不同的查询,我SQL笛卡尔连接的输出,这导致每一行子对象都重复父对象的行。我需要找出基于复合键的不同的父对象,然后在列表中为父对象添加每个子对象,并将其设置为父对象的属性
我能够根据父对象的组合键找到不同的父对象。以下是相关代码
private static <T> Predicate<T> distinctByKeys(Function<? super T, ?>... keyExtractors)
{
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
return t ->
{
final List<?> keys = Arrays.stream(keyExtractors)
.map(ke -> ke.apply(t))
collect(Collectors.toList());
return seen.putIfAbsent(keys, Boolean.TRUE) == null;
};
}
假设我有以下输入
list.add(new Book("Core Java", 200, new ArrayList(){{add("Page 1");}}));
list.add(new Book("Core Java", 200, new ArrayList(){{add("Page 2");}}));
list.add(new Book("Learning Freemarker", 150, new ArrayList(){{add("Page 15");}}));
list.add(new Book("Spring MVC", 300, new ArrayList(){{add("Page 16");}}));
list.add(new Book("Spring MVC", 300, new ArrayList(){{add("Page 17");}}));
我需要产生以下输出
Core Java,200, [Page 1, Page 2]
Learning Freemarker,150, [Page 15]
Spring MVC,300 , [Page 16, Page 17]
这方面的任何帮助都会很有帮助
一个选项是使用收集器。toMap()
使用标题
和页面
值作为键。如果发现重复项,则可以合并两个列表:
Collection<Book> result = list.stream()
.collect(Collectors.toMap(
b -> Map.entry(b.getTitle(), b.getPages()),
b -> new Book(b.getTitle(), b.getPages(), b.getList()),
(b1, b2) -> new Book(b1.getTitle(), b1.getPages(),
Stream.concat(b1.getList().stream(), b2.getList().stream()).collect(Collectors.toList())),
LinkedHashMap::new))
.values();
或者,您可以使用收集器。groupingBy()
:
List<Book> result = list.stream().collect(
Collectors.groupingBy(b -> Map.entry(b.getTitle(), b.getPages()), LinkedHashMap::new,
Collectors.flatMapping(b -> b.getList().stream(), Collectors.toList())))
.entrySet().stream()
.map(e -> new Book(e.getKey().getKey(), e.getKey().getValue(), e.getValue()))
.collect(Collectors.toList());
第二种方法使用title
和page
作为键创建一个Map,并使用Collectors.flat映射()
合并所有书籍的列表。之后,您将条目映射回Book对象。
如果无法使用采集器。flatMapping()
使用收集器。mapping()`相反:
List<Book> r = list.stream().collect(
Collectors.groupingBy(b -> Map.entry(b.getTitle(), b.getPages()), LinkedHashMap::new,
Collectors.mapping(Book::getList, Collectors.toList())))
.entrySet().stream()
.map(e -> new Book(e.getKey().getKey(), e.getKey().getValue(),
e.getValue().stream().flatMap(Collection::stream).collect(Collectors.toList())))
.collect(Collectors.toList());
如果不能使用Map.entry()
,请使用new AbstractMap。简单入口
这两种情况的结果都是:
Book[title='Core Java', pages=200, list=[Page 1, Page 2]]
Book[title='Learning Freemarker', pages=150, list=[Page 15]]
Book[title='Spring MVC', pages=300, list=[Page 16, Page 17]]
我有以下Java POJO 如何实现在游戏对象列表中确定重复字段的功能? 例如,当两个游戏有相同的开始日期? 我以前使用过,但仅在根据最早日期等对对象进行排序时使用过,但它能否用于对重复项进行排序?
父类: 子电话对象(第一级): 我正在尝试获取person对象,其phone对象类型为home,其编号应包含“888”。 从上面的流代码,我能够得到手机对象。但是如何在相同的函数中获得该电话对象的父对象呢?。 我尝试了这种方式,我得到null不匹配的对象。
我需要筛选我的对象列表: 以便将具有相同和的所有对象合并到具有以下属性的单个对象中: 作为所有值的和 作为所有值的字符串级联 所以结果是: Java 8中的溪流有可能做到吗? 我尝试了几种方法(例如,还使用),但我没有找到解决方案! 谢谢 编辑: 下面是我尝试的: 但由于某种原因,在计算过程中,我在上得到了,无论如何,我非常肯定这不是一个有效的解决方案。
假设我们有: 我们有一个实例列表,即
请建议更好的方法将路线转换为路线地图。
当我对它进行降序排序时,它应该首先显示Parent3,因为它有一个Z。这是我当前的hql,它得到了1>2>3的错误结果: 如果没有distinct,尽管它选择了多个相同的父级,但它仍然很好。 我有一个模型设置如下: 编辑:在集合中按HQL顺序对其进行排序,尽管当双亲具有相同的children.name值时,它不会比较下一个可能的值。即。 如果Parent1有孩子abba,zeon Parent2有