我有一份Thingy pojos列表,这样:
public class Thingy {
private DifferentThingy nestedThingy;
public DifferentThingy getNestedThingy() {
return this.nestedThingy;
}
}
...
public class DifferentThingy {
private String attr;
public String getAttr() {
return this.attr;
}
}
我想过滤
List<Thingy>
基于
是唯一的attr
Thingy的
DifferentThingy
这是我到目前为止所尝试的内容:
private List<Thingy> getUniqueBasedOnDifferentThingyAttr(List<Thingy> originalList) {
List<Thingy> uniqueItems = new ArrayList<Thingy>();
Set<String> encounteredNestedDiffThingyAttrs= new HashSet<String>();
for (Thingy t: originalList) {
String nestedDiffThingyAttr = t.getNestedThingy().getAttr();
if(!encounteredNestedDiffThingyAttrs.contains(nestedDiffThingyAttr)) {
encounteredNestedDiffThingyAttrs.add(nestedDiffThingyAttr);
uniqueItems.add(t);
}
}
return uniqueItems;
}
我想使用Java 8流和lambdas为两个getter最终检索用于确定唯一性的属性,但我不确定如何。当比较属性位于pojo的顶层时,我知道怎么做,但是当属性嵌套在另一个对象中时却不知道。
答案 0 :(得分:4)
你可以这样做:
originalList.stream()
.collect(Collectors.toMap(thing -> thing.getNestedThingy().getAttr(), p -> p, (p, q) -> p))
.values();
不确定是否是最佳方式,我在Android上,所以不要在日常工作中使用流。
<强> UPD 强>
如果某人无法编译,我的测试文件有full code。
答案 1 :(得分:4)
如何使用javaslang
使其更明确javaslang.collection.List.ofAll(thingies)
.distinctBy(t -> t.getNestedThingy().getAttr());
Javaslang核心是Java 8+的功能库。它有助于减少代码量并提高稳健性。功能编程的第一步是开始思考不可变的值。 Javaslang提供了不可变的集合以及对这些值进行操作的必要函数和控制结构。结果很美,只是工作。
答案 2 :(得分:2)
我保留了一组独特的嵌套东西的属性......
然后我尝试添加一个元素。
当集合“增长”时,意味着遇到了一个唯一的元素。
当设置大小未更改时,表示此Thingy
具有已遇到属性的NestedThingy
。
再加上一个简单的测试:
public class Thingies {
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
final Set<Object> seen = Collections.synchronizedSet(new HashSet<>());
return t -> seen.add(keyExtractor.apply(t));
}
private static List<Thingy> getUniqueBasedOnDifferentThingyAttr(List<Thingy> originalList) {
return originalList.stream()
.filter(distinctByKey(thingy -> thingy.getNestedThingy().getAttr()))
.collect(toList());
}
public static void main(String[] args) {
List<Thingy> originalList = new ArrayList<>();
originalList.add(new Thingy(new DifferentThingy("first")));
originalList.add(new Thingy(new DifferentThingy("first")));
originalList.add(new Thingy(new DifferentThingy("second")));
System.out.println(getUniqueBasedOnDifferentThingyAttr(originalList));
}
}
输出:
[first, second]
帮助OP的原始答案(有点冗长且对并行流不利)包含这样的方法:
private static List<Thingy> getUniqueBasedOnDifferentThingyAttr(List<Thingy> originalList) {
final Set<String> uniqueAttributes = new HashSet<>(originalList.size());
return originalList.stream()
.filter(thingy -> {
int initialSize = uniqueAttributes.size();
uniqueAttributes.add(thingy.getNestedThingy().getAttr());
return initialSize != uniqueAttributes.size();
}).collect(toList());
}
答案 3 :(得分:2)
您可以使用比较器达到子对象属性的TreeSet
:
private static List<Thingy> getUniqueBasedOnDifferentThingyAttr(List<Thingy> originalList) {
Set<Thingy> uniqueSet = new TreeSet<Thingy>(Comparator.comparing(thingy -> thingy.getNestedThingy().getAttr()));
return originalList.stream()
.filter(uniqueSet::add)
.collect(Collectors.toList());
}
uniqueSet::add
会产生足够的唯一性过滤器,因为只有当项目不在集合中时才会返回true。
答案 4 :(得分:0)
使用StreamEx:
StreamEx.of(originalList).distinct(e -> e.getNestedThingy().getAttr()).toList();
Stream.of(originalList).distinct(e -> e.getNestedThingy().getAttr()).toList();