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)獲取不同的元素。因此,需要去重的類(lèi)必須實(shí)現(xiàn)hashCode()和equals()方法。也就是說(shuō),可以通過(guò)重寫(xiě)定制的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í)體類(lèi)列表去重
@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類(lèi)型,原理就是通過(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的Junit測(cè)試框架中的其他注解說(shuō)明
這篇文章主要介紹了Java的Junit測(cè)試框架中的其他注解說(shuō)明,JUnit是一個(gè)開(kāi)源的java單元測(cè)試框架,它是XUnit測(cè)試體系架架構(gòu)的一種體現(xiàn),2023-10-10
是Java語(yǔ)言事實(shí)上的標(biāo)準(zhǔn)單元測(cè)試庫(kù),需要的朋友可以參考下
SpringBoot實(shí)現(xiàn)列表數(shù)據(jù)導(dǎo)出為Excel文件
這篇文章主要為大家詳細(xì)介紹了在Spring?Boot框架中如何將列表數(shù)據(jù)導(dǎo)出為Excel文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-02-02
mybatisPlus 大于小于的實(shí)現(xiàn)示例
在 MyBatis Plus 中進(jìn)行條件查詢(xún),使用小于等于,大于等于操作可以通過(guò)其提供的條件構(gòu)造器(Wrapper)來(lái)實(shí)現(xiàn),下面就來(lái)詳細(xì)的介紹一下mybatisPlus 大于小于的實(shí)現(xiàn)示例,感興趣的可以了解一下2025-12-12
一文帶你看懂Android動(dòng)畫(huà)的實(shí)現(xiàn)原理
動(dòng)畫(huà)是 Android 應(yīng)用程序中重要的交互特性,ndroid 提供了多種動(dòng)畫(huà)效果,包括平移、縮放、旋轉(zhuǎn)和透明度等,它們可以通過(guò)代碼或 XML 來(lái)實(shí)現(xiàn),本文將介紹 Android 動(dòng)畫(huà)的原理和實(shí)現(xiàn)方法,并提供一些示例,需要的朋友可以參考下2023-07-07
myeclipse創(chuàng)建servlet_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了myeclipse創(chuàng)建servlet的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
MacBook Java開(kāi)發(fā)環(huán)境搭建的詳細(xì)步驟(新手必備)
本文主要介紹了MacBook Java開(kāi)發(fā)環(huán)境搭建,文中通過(guò)圖文示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
InputStream數(shù)據(jù)結(jié)構(gòu)示例解析
這篇文章主要為大家介紹了InputStream數(shù)據(jù)結(jié)構(gòu)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10

