Java8使用stream查找重復(fù)元素的方法示例
一、查重方法
public static <E> List<E> getDuplicateElements(List<E> list) {
return list.stream() // list 對(duì)應(yīng)的 Stream
.collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) // 獲得元素出現(xiàn)頻率的 Map,鍵為元素,值為元素出現(xiàn)的次數(shù)
.entrySet().stream() // 所有 entry 對(duì)應(yīng)的 Stream
.filter(entry -> entry.getValue() > 1) // 過(guò)濾出元素出現(xiàn)次數(shù)大于 1 的 entry
.map(entry -> entry.getKey()) // 獲得 entry 的鍵(重復(fù)元素)對(duì)應(yīng)的 Stream
.collect(Collectors.toList()); // 轉(zhuǎn)化為 List
}二、測(cè)試
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("a", "b", "c", "d", "a", "a", "d", "d","c","b","e","f");
List<String> duplicateElements = getDuplicateElements(list);
System.out.println("list 中重復(fù)的元素:" + duplicateElements);
}運(yùn)行結(jié)果
list 中重復(fù)的元素:[a, b, c, d]




拓展知識(shí)
Java8通過(guò)stream對(duì)列表去重:
1、Stream的distinct()方法
distinct()方法是Java 8中Stream提供的方法。返回的是由該流中不同元素組成的流。distinct()方法使用hashCode()和equals()方法來(lái)獲取不同的元素。因此,需要去重的類必須實(shí)現(xiàn)hashCode()和equals()方法。也就是說(shuō),可以通過(guò)重寫定制的hashCode()和equals()方法來(lái)達(dá)到特殊需求的去重。
distinct()方法聲明:
Stream<T> distinct();
String列表去重
List<String> stringList = new ArrayList<String>() {{
add("A");
add("A");
add("B");
add("B");
add("C");
}};
List<String> newStringList = stringList.stream().distinct().collect(Collectors.toList());
for (String s : newStringList) {
System.out.println(s);
}實(shí)體類列表去重
@Test
public void test2() throws JsonProcessingException {
String s = "[\n" +
"\t{\n" +
" \"stuNo\": \"001\",\n" +
" \"name\": \"Tom\"\n" +
" }, {\n" +
" \"stuNo\": \"002\",\n" +
" \"name\": \"Mike\"\n" +
" }, {\n" +
" \"stuNo\": \"001\",\n" +
" \"name\": \"Tom\"\n" +
" }\n" +
"]";
ObjectMapper objectMapper = new ObjectMapper();
List<Student> studentList = objectMapper.readValue(s, new TypeReference<List<Student>>() {
});
List<Student> collect= studentList.stream().distinct().collect(Collectors.toList());
System.out.println(objectMapper.writeValueAsString(collect));
}List<Object> 根據(jù)Object中某個(gè)屬性去重
方式一:Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>
@Test
public void test3() throws JsonProcessingException {
String s = "[\n" +
"\t{\n" +
" \"stuNo\": \"001\",\n" +
" \"name\": \"Tom\"\n" +
" }, {\n" +
" \"stuNo\": \"002\",\n" +
" \"name\": \"Mike\"\n" +
" }, {\n" +
" \"stuNo\": \"001\",\n" +
" \"name\": \"Tom\"\n" +
" }\n" +
"]";
ObjectMapper objectMapper = new ObjectMapper();
List<Student> studentList = objectMapper.readValue(s, new TypeReference<List<Student>>() {
});
List<Student> collect= studentList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new)
);
System.out.println(objectMapper.writeValueAsString(collect));
}方式二:通過(guò)filter()方法
創(chuàng)建一個(gè)方法作為Stream.filter()的參數(shù),其返回值為Predicate類型,原理就是通過(guò)判斷一個(gè)元素能否加入到set中。
public static void main(String[] args) {
Person p = new Person();
p.setName("1");
Person p2 = new Person();
p2.setName("2");
Person p3 = new Person();
p3.setName("1");
List<Person> ps = new ArrayList<>();
ps.add(p);
ps.add(p2);
ps.add(p3);
List<Person> collect = ps.stream().filter(distinctByKey(new Function<Person, Object>() {
@Override
public Object apply(Person person) {
return person.getName();
}
})).collect(Collectors.toList());
System.out.println(JSON.toJSONString(collect));
}
/**
* 此方法能根據(jù)不為空的字段值去重
* 要求person.getName()不能為空
*/
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
/**
* 當(dāng)字段值不為空的字段值去重,為空的數(shù)據(jù)不過(guò)濾
* person.getName()的值可為空
*
* @return 返回屬性值為空的數(shù)據(jù)+屬性值不為空且去重的數(shù)據(jù)之和
*/
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
Predicate<T> predicate = new Predicate<T>() {
@Override
public boolean test(T t) {
Object o = keyExtractor.apply(t);
if (ObjectUtils.isEmpty(o)) {
return true;
}
return seen.add(o);
}
};
}到此這篇關(guān)于Java8使用stream查找重復(fù)元素的方法示例的文章就介紹到這了,更多相關(guān)Java8 stream重復(fù)元素內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java?數(shù)組越界判斷和獲取數(shù)組長(zhǎng)度的實(shí)現(xiàn)方式
這篇文章主要介紹了java?數(shù)組越界判斷和獲取數(shù)組長(zhǎng)度的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
詳解Spring boot使用Redis集群替換mybatis二級(jí)緩存
本篇文章主要介紹了詳解Spring boot使用Redis集群替換mybatis二級(jí)緩存,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
如何解決java:錯(cuò)誤:無(wú)效的源發(fā)行版:17問(wèn)題
這篇文章主要介紹了如何解決java:錯(cuò)誤:無(wú)效的源發(fā)行版:17問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Hibernate初體驗(yàn)及簡(jiǎn)單錯(cuò)誤排除代碼詳解
這篇文章主要介紹了Hibernate初體驗(yàn)及簡(jiǎn)單錯(cuò)誤排除代碼詳解,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02
springboot整合日志處理Logback的實(shí)現(xiàn)示例
Logback是由log4j創(chuàng)始人設(shè)計(jì)的又一個(gè)開(kāi)源日志組件,本文主要介紹了springboot整合日志處理Logback,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01

