使用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
