说到集合去重,java8提供了distinct
可以实现大部分情况的去重,当然,你如果不嫌麻烦,可以自己写for循环去重。今天我们就来讲讲如何合理使用java8的特性实现去重。
1、字符串集合去重
字符串去重事最简单的去重,直接使用stream流的distinct就可以实现去重。
List<String> list = Arrays.asList("abc","bcd","cda","abc");
List<String> list2 = list.stream().distinct().collect(Collectors.toList());
list2的结果为{“abc”,“bcd”,“cda”},去重成功。
2、对象集合去重
对象去重稍微比字符串去重麻烦一点,但也比较简单,也可以使用distinct达到去重的目的。distinct去重依据的事equals方法,我们只需要重写对象的hashcode()
和equals()
方法,就能实现按照指定某些字段对这个对象进行去重。有一点需要注意,idea自动生成的hashcode()
和equals()
方法,除了你选中的属性外,还包含父类的hash值和equals比较方法,如果你去重不需要关心父类属性,手动删除这一块代码。重写了hashcode()
和equals()
方法后,再使用和字符串去重一样的方式去重。
3、创建StreamUtils工具类,使用静态方法去重
public class StreamUtils {
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
public static <T> Predicate<T> distinctByKeys(Function<? super T, ?>... keyExtractors) {
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>(16);
return t ->
{
final List<?> keys = Arrays.stream(keyExtractors)
.map(ke -> ke.apply(t))
.collect(Collectors.toList());
return seen.putIfAbsent(keys, Boolean.TRUE) == null;
};
}
}
工具类包含2个静态方法,distinctByKey
是根据对象某个属性去重,distinctByKeys
是根据对象多个属性去重。其中前者依据HashSet
元素不能重复的特性去重,后者是依据HashMap
键不能重复的特性去重。
具体使用方式如下:
@Data
@NoArgsConstructor
@AllArgsConstructor
public Class A {
private String a;
private Integer b;
private String c;
}
List<String> list = Arrays.asList(new A("a",1,"c"),new A("a",1,"b"),new A("a",2,"d"));
List<String> list2 = list.stream().filter(StreamUtils.distinctByKey(A::getA)).collect(Collectors.toList());
List<String> list3 = list.stream().filter(StreamUtils.distinctByKeys(A::getA,A:getB)).collect(Collectors.toList());
list1根据类A的a属性去重,list2根据类A的a属性和b属性去重。