Java 使用收集器按两个值进行流过滤
Java Stream filter by two values using collectors
我有下面的工作代码使用一个值进行比较但想与两个值进行比较。我需要添加一个过滤器作为“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”
“操作 PICKEUP 地址 ID 1112”
但我想要的结果是:
“已交付地址 ID 1112”
“已交付地址 ID 1113”
“PICKEUP 地址 ID 1112”
您可以使用 thenComparing
链接比较器,即
new TreeSet<>(Comparator.comparing(Data::getAction).thenComparing(Comparator.comparing(Data::otherMethod))
如果我没看错,您正试图通过组合两个属性 addressID & action
从您的列表中获取不同的项目。 Here 是一个公认的答案,感谢@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;
};
}
我有下面的工作代码使用一个值进行比较但想与两个值进行比较。我需要添加一个过滤器作为“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” “操作 PICKEUP 地址 ID 1112”
但我想要的结果是: “已交付地址 ID 1112” “已交付地址 ID 1113” “PICKEUP 地址 ID 1112”
您可以使用 thenComparing
链接比较器,即
new TreeSet<>(Comparator.comparing(Data::getAction).thenComparing(Comparator.comparing(Data::otherMethod))
如果我没看错,您正试图通过组合两个属性 addressID & action
从您的列表中获取不同的项目。 Here 是一个公认的答案,感谢@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;
};
}