使用distinctByKeys()函数根据多字段区分
下面的例子中,定义了一个函数,我们可以传递多个键提取器(我们要过滤重复项的字段)。
此函数创建一个键为 List
,其中列表包含字段的值以检查不同的条件。
列表键被插入到一个“ConcurrentHashMap”中,它只存储唯一和不同的键。
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; }; }
示例: 找出不同id和名称的记录:
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; @SuppressWarnings("unchecked") public class Main { public static void main(String[] args) { List<Record> recordsList = getRecords(); List<Record> list = recordsList .stream() .filter(distinctByKeys(Record::getId, Record::getName)) .collect(Collectors.toList()); System.out.println(list); } 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; }; } private static ArrayList<Record> getRecords() { ArrayList<Record> records = new ArrayList<>(); records.add(new Record(1l, 10l, "record1", "record1@email.com", "Netherlands")); records.add(new Record(1l, 20l, "record1", "record1@email.com", "Netherlands")); records.add(new Record(2l, 30l, "record2", "record2@email.com", "Netherlands")); records.add(new Record(2l, 40l, "record2", "record2@email.com", "Netherlands")); records.add(new Record(3l, 50l, "record3", "record3@email.com", "Netherlands")); return records; } }
https://onitroad.com 更多教程
根据自定义key类的多属性找出唯一元素
另一种可能的方法是使用一个自定义类来表示 POJO 类的不同键。
下面的示例中,创建了一个类 CustomKey,它有一些字段,可以根据所有这些字段的不同值组合从列表中获取 不同的元素(distinct)。
public class CustomKey { private long id; private String name; public CustomKey(final Record record) { this.id = record.getId(); this.name = record.getName(); } //Getters and setters @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (id ^ (id >>> 32)); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CustomKey other = (CustomKey) obj; if (id != other.id) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
示例: 根据给定的多个字段从列表中过滤不同的元素。
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; @SuppressWarnings("unchecked") public class Main { public static void main(String[] args) { List<Record> recordsList = getRecords(); List<Record> list = recordsList.stream() .filter(distinctByKey(CustomKey::new)) .collect(Collectors.toList()); System.out.println(list); } public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) { Map<Object, Boolean> seen = new ConcurrentHashMap<>(); return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } private static ArrayList<Record> getRecords() { ArrayList<Record> records = new ArrayList<>(); records.add(new Record(1l, 10l, "record1", "record1@email.com", "Netherlands")); records.add(new Record(1l, 20l, "record1", "record1@email.com", "Netherlands")); records.add(new Record(2l, 30l, "record2", "record2@email.com", "Netherlands")); records.add(new Record(2l, 40l, "record2", "record2@email.com", "Netherlands")); records.add(new Record(3l, 50l, "record3", "record3@email.com", "Netherlands")); return records; } }
Record 类:
public class Record { private long id; private long count; private String name; private String email; private String location; public Record(long id, long count, String name, String email, String location) { super(); this.id = id; this.count = count; this.name = name; this.email = email; this.location = location; } //Getters and setters @Override public String toString() { return "Record [id=" + id + ", count=" + count + ", name=" + name + ", email=" + email + ", location=" + location + "]"; } }
日期:2020-09-17 00:10:06 来源:oir作者:oir