Java 8基于嵌套对象属性过滤pojo列表

fcg9iug3  于 2023-01-11  发布在  Java
关注(0)|答案(5)|浏览(167)

我有一个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

那个东西的

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流和两个getter的lambdas来完成这个操作,这两个getter最终会检索用于确定唯一性的属性,但我不确定如何操作。我知道当用于比较的属性位于pojo的顶层时如何操作,但不知道当属性嵌套在另一个对象中时如何操作。

tv6aics1

tv6aics11#

你可以这样做:

originalList.stream()
    .collect(Collectors.toMap(thing -> thing.getNestedThingy().getAttr(), p -> p, (p, q) -> p))
    .values();

不知道是否最佳的方式虽然,我在Android上,所以不要在日常工作中使用流.

统一采购司

对于有人不能编译它,有我的测试文件full code

voase2hg

voase2hg2#

使用javaslang使其更加明确如何

javaslang.collection.List.ofAll(thingies)
  .distinctBy(t -> t.getNestedThingy().getAttr());

Javaslang核心是Java 8+的函数库。它有助于减少代码量和增加健壮性。函数编程的第一步是开始考虑不可变的值。Javaslang提供不可变的集合以及必要的函数和控制结构来操作这些值。结果很漂亮,而且很好用。

w8rqjzmb

w8rqjzmb3#

我保留了一组嵌套的唯一属性......然后我尝试向其中添加一个元素。当集合"增长"时,意味着遇到了一个唯一元素。当集合大小不变时,意味着这个Thingy有一个NestedThingy,该Thingy有一个已经遇到的属性。下面是一个简单的测试:

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());
}
gzjq41n4

gzjq41n44#

你可以使用一个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。

fiei3ece

fiei3ece5#

使用StreamEx时:

StreamEx.of(originalList).distinct(e -> e.getNestedThingy().getAttr()).toList();

或通过abacus-common

Stream.of(originalList).distinct(e -> e.getNestedThingy().getAttr()).toList();

相关问题