Java8使用stream查找重復(fù)元素的方法示例
一、查重方法
public static <E> List<E> getDuplicateElements(List<E> list) { return list.stream() // list 對應(yīng)的 Stream .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) // 獲得元素出現(xiàn)頻率的 Map,鍵為元素,值為元素出現(xiàn)的次數(shù) .entrySet().stream() // 所有 entry 對應(yīng)的 Stream .filter(entry -> entry.getValue() > 1) // 過濾出元素出現(xiàn)次數(shù)大于 1 的 entry .map(entry -> entry.getKey()) // 獲得 entry 的鍵(重復(fù)元素)對應(yīng)的 Stream .collect(Collectors.toList()); // 轉(zhuǎn)化為 List }
二、測試
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]
拓展知識
Java8通過stream對列表去重:
1、Stream的distinct()方法
distinct()方法是Java 8中Stream提供的方法。返回的是由該流中不同元素組成的流。distinct()方法使用hashCode()和equals()方法來獲取不同的元素。因此,需要去重的類必須實(shí)現(xiàn)hashCode()和equals()方法。也就是說,可以通過重寫定制的hashCode()和equals()方法來達(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)); }
方式二:通過filter()方法
創(chuàng)建一個(gè)方法作為Stream.filter()的參數(shù),其返回值為Predicate類型,原理就是通過判斷一個(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ù)不過濾 * 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java?數(shù)組越界判斷和獲取數(shù)組長度的實(shí)現(xiàn)方式
這篇文章主要介紹了java?數(shù)組越界判斷和獲取數(shù)組長度的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12詳解Spring boot使用Redis集群替換mybatis二級緩存
本篇文章主要介紹了詳解Spring boot使用Redis集群替換mybatis二級緩存,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05如何解決java:錯(cuò)誤:無效的源發(fā)行版:17問題
這篇文章主要介紹了如何解決java:錯(cuò)誤:無效的源發(fā)行版:17問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07Hibernate初體驗(yàn)及簡單錯(cuò)誤排除代碼詳解
這篇文章主要介紹了Hibernate初體驗(yàn)及簡單錯(cuò)誤排除代碼詳解,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02springboot整合日志處理Logback的實(shí)現(xiàn)示例
Logback是由log4j創(chuàng)始人設(shè)計(jì)的又一個(gè)開源日志組件,本文主要介紹了springboot整合日志處理Logback,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01