Java Stream 使用收集器按两个值进行过滤

发布于 2025-01-14 13:33:33 字数 1353 浏览 7 评论 0原文

我有下面的工作代码,使用一个值进行比较,但想与两个值进行比较。我需要再添加一个过滤器作为“getAddressID”以及 getAction。有人可以帮我修改下面的代码吗?

List<Data> finalData = dataList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparing(Data::getAction))),
            ArrayList::new))
public class TestCollection {

/**
 * @param args
 */
public static void main(String[] args) {
    
    List<Data> dataList = new ArrayList<Data>();
    
    Data data1 = new Data("DELIVERED", "1112");
    Data data2 = new Data("DELIVERED", "1113");
    Data data3 = new Data("PICKEUP", "1112");
    Data data4 = new Data("PICKEUP", "1112");
    
    dataList.add(data1);
    dataList.add(data2);
    dataList.add(data3);
    dataList.add(data4);
    
    //Filer by Action
    List<Data> finalData = dataList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<> (Comparator.comparing(Data::getAction))), ArrayList::new));
    
    for(Data data : finalData) {
        System.out.println(" Action " + data.getAction() + " Address ID " + data.getAddressID());
    }
    
    

}

结果

是: “操作已交付地址 ID 1112” “Action PICKEUP Address ID 1112”

但我想要结果为: “已交付地址 ID 1112” “已交付地址 ID 1113” “取货地址 ID 1112”

I have the below working code using one value to compare but want to compare with two values. I need to add one more filter as "getAddressID" along with getAction. Could some help me to modify the below code?

List<Data> finalData = dataList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparing(Data::getAction))),
            ArrayList::new))
public class TestCollection {

/**
 * @param args
 */
public static void main(String[] args) {
    
    List<Data> dataList = new ArrayList<Data>();
    
    Data data1 = new Data("DELIVERED", "1112");
    Data data2 = new Data("DELIVERED", "1113");
    Data data3 = new Data("PICKEUP", "1112");
    Data data4 = new Data("PICKEUP", "1112");
    
    dataList.add(data1);
    dataList.add(data2);
    dataList.add(data3);
    dataList.add(data4);
    
    //Filer by Action
    List<Data> finalData = dataList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<> (Comparator.comparing(Data::getAction))), ArrayList::new));
    
    for(Data data : finalData) {
        System.out.println(" Action " + data.getAction() + " Address ID " + data.getAddressID());
    }
    
    

}

}

The result is :
"Action DELIVERED Address ID 1112"
"Action PICKEUP Address ID 1112"

But I want result as:
"DELIVERED Address ID 1112"
"DELIVERED Address ID 1113"
"PICKEUP Address ID 1112"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感受沵的脚步 2025-01-21 13:33:33

您可以使用 thenComparing 链接比较器,即

new TreeSet<>(Comparator.comparing(Data::getAction).thenComparing(Comparator.comparing(Data::otherMethod))

You can chain your comparators using thenComparing, ie

new TreeSet<>(Comparator.comparing(Data::getAction).thenComparing(Comparator.comparing(Data::otherMethod))
为你鎻心 2025-01-21 13:33:33

如果我猜对了,您将尝试通过两个属性 addressID & 的组合从列表中获取不同的项目。行动。 这里是一个可接受的答案,感谢@Stuart Marks,它致力于通过一个属性获取不同的元素。可以进一步修改以解决您的用例,例如:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


....

List<Data> dataList = // your data objects

List<Data> distinctData = dataList.stream()
            .filter(distinctByKeys(Data::getAction, Data::getAddressID))
            .collect(Collectors.toList());

方法 distinctByKeys 可能看起来像

private static <T> Predicate<T> distinctByKeys(final 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;
    };
}

If I get it right, you are trying to get distinct items from your list by the combination of the two properties addressID & action. Here is a an accepted answer, thanks to @Stuart Marks, which works to get distinct elements by one property. That could be further modified to solve your use case like:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


....

List<Data> dataList = // your data objects

List<Data> distinctData = dataList.stream()
            .filter(distinctByKeys(Data::getAction, Data::getAddressID))
            .collect(Collectors.toList());

where the method distinctByKeys could look like

private static <T> Predicate<T> distinctByKeys(final 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;
    };
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文