欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java8-Stream流操作List去重問題

 更新時(shí)間:2022年11月11日 15:21:17   作者:徐壽春  
這篇文章主要介紹了Java8-Stream流操作List去重問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Java8Stream流操作List去重

根據(jù)屬性去重整體去重使用

  • distinct
ArrayList<LabelInfoDTO> collect = labelInfoDTOS.stream().
collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(LabelInfoDTO::getLabelCode))), ArrayList::new));

List列表運(yùn)用Java8的stream流按某字段去重

問題

項(xiàng)目中經(jīng)常會遇到列表去重的問題,一般可使用Java8的stream()流提供的distinct()方法:list.stream().distinct()。

list的類型為List<String>、List<Integer>,list里的元素為簡單包裝類型。

或者List<Xxx>,其中Xxx為自定義對象類型,重寫equals和hashCode方法,可根據(jù)業(yè)務(wù)情況來實(shí)現(xiàn),如id相同即認(rèn)為對象相等。

有時(shí)會遇到這種情況,需要對按對象里的某字段來去重。

例如:

@NoArgsConstructor
@AllArgsConstructor
@Data
class Book {
?
? ? public static Book of(Long id, String name, String createTime) {
? ? ? ? return new Book(id, name, Date.from(LocalDateTime.parse(createTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).atZone(ZoneId.systemDefault()).toInstant()));
? ? }
?
? ? private Long id;
?
? ? private String name;
?
? ? private Date createTime;
}

現(xiàn)在我們要按name字段來去重,假設(shè)list如下:

List<Book> books = new ArrayList<>();
books.add(Book.of(1L, "Thinking in Java", "2021-06-29 17:13:14"));
books.add(Book.of(2L, "Hibernate in action", "2021-06-29 18:13:14"));
books.add(Book.of(3L, "Thinking in Java", "2021-06-29 19:13:14"));

思路

1、重寫B(tài)ook類的equals和hashCode方法,以name來判斷比較是否相同,然后用stream的distinct方法來去重

代碼:

class Book {
? ? ...
?
? ? @Override
? ? public String toString() {
? ? ? ? return String.format("(%s,%s,%s)", id, name, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
? ? }
?
? ? @Override
? ? public boolean equals(Object o) {
? ? ? ? if (this == o) return true;
? ? ? ? if (o == null || getClass() != o.getClass()) return false;
? ? ? ? Book book = (Book) o;
? ? ? ? return Objects.equals(name, book.name);
? ? }
}
?
List<Book> distinctNameBooks1 = books.stream().distinct().collect(Collectors.toList());
System.out.println(distinctNameBooks1);

總結(jié):

通過重寫equals和hashCode方法,按實(shí)際需求來比較,可直接使用stream的distinct方法去重,比較方便;

有時(shí)對象類不方便或者不能修改,如它已實(shí)現(xiàn)好或者是引用的三方包不能修改,該方法不能靈活地按字段來去重。

2、通過Collectors.collectingAndThen的Collectors.toCollection,里面用TreeSet在構(gòu)造函數(shù)中指定字段

代碼:

List<Book> distinctNameBooks2 = books.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName()))), ArrayList::new));
System.out.println(distinctNameBooks2);

總結(jié):

使用stream流提供的方法,代碼很簡潔,但不足是雖然實(shí)現(xiàn)了去重效果,但list里的順序變化了,而有的場景需要保持順序。

3、通過stream的filter方法來去重,定義一個(gè)去重方法,參數(shù)為Function類型,返回值為Predicate類型

代碼:

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
? ? Map<Object, Boolean> map = new HashMap<>();
? ? return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
?
List<Book> distinctNameBooks3 = books.stream().filter(distinctByKey(o -> o.getName())).collect(Collectors.toList());
System.out.println(distinctNameBooks3);

總結(jié):

通過封裝定義一個(gè)去重方法,配合filter方法可靈活的按字段去重,保持了原列表的順序,不足之處是內(nèi)部定義了一個(gè)HashMap,有一定內(nèi)存占用,并且多了一個(gè)方法定義。

4、通過stream的filter方法來去重,不定義去重方法,在外面創(chuàng)建HashMap

代碼:

Map<Object, Boolean> map = new HashMap<>();
List<Book> distinctNameBooks4 = books.stream().filter(i -> map.putIfAbsent(i.getName(), Boolean.TRUE) == null).collect(Collectors.toList());
System.out.println(distinctNameBooks4);

總結(jié):

仍然是配合filter方法實(shí)現(xiàn)去重,沒有單獨(dú)創(chuàng)建方法,臨時(shí)定義一個(gè)HashMap,保持了原列表的順序,不足之處是有一定內(nèi)存占用。

PS:暫時(shí)沒找到stream流原生支持的可按某字段去重并且保持原列表順序的方法

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Nacos心跳時(shí)間配置及服務(wù)快速上下線方式

    Nacos心跳時(shí)間配置及服務(wù)快速上下線方式

    這篇文章主要介紹了Nacos心跳時(shí)間配置及服務(wù)快速上下線方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • SpringCloud如何創(chuàng)建一個(gè)服務(wù)提供者provider

    SpringCloud如何創(chuàng)建一個(gè)服務(wù)提供者provider

    這篇文章主要介紹了SpringCloud如何創(chuàng)建一個(gè)服務(wù)提供者provider,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • java實(shí)用驗(yàn)證碼的實(shí)現(xiàn)代碼

    java實(shí)用驗(yàn)證碼的實(shí)現(xiàn)代碼

    這篇文章主要為大家介紹了java實(shí)用驗(yàn)證碼的實(shí)現(xiàn)代碼,驗(yàn)證碼實(shí)際上就是隨機(jī)選擇一些字符以圖片的形式展現(xiàn)在頁面上,感興趣的小伙伴們可以參考一下
    2016-03-03
  • 詳解java 中的CAS與ABA

    詳解java 中的CAS與ABA

    這篇文章主要介紹了java 中的CAS與ABA的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05
  • Java項(xiàng)目中大批量數(shù)據(jù)查詢導(dǎo)致OOM的解決

    Java項(xiàng)目中大批量數(shù)據(jù)查詢導(dǎo)致OOM的解決

    本文主要介紹了Java項(xiàng)目中大批量數(shù)據(jù)查詢導(dǎo)致OOM的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • JAVA序列化和反序列化的底層實(shí)現(xiàn)原理解析

    JAVA序列化和反序列化的底層實(shí)現(xiàn)原理解析

    這篇文章主要介紹了JAVA序列化和反序列化的底層實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 詳解Java常用工具類—泛型

    詳解Java常用工具類—泛型

    這篇文章主要介紹了Java常用工具類—泛型,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Java StringBuffer與StringBuilder有什么區(qū)別

    Java StringBuffer與StringBuilder有什么區(qū)別

    當(dāng)對字符串進(jìn)行修改的時(shí)候,需要使用 StringBuffer 和 StringBuilder類,和String類不同的是,StringBuffer和 StringBuilder類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象,本篇我們來分析分析它們的區(qū)別
    2023-01-01
  • mybatis-plus主鍵id生成、字段自動填充的實(shí)現(xiàn)代碼

    mybatis-plus主鍵id生成、字段自動填充的實(shí)現(xiàn)代碼

    這篇文章主要介紹了mybatis-plus主鍵id生成、字段自動填充的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Java中i++的一些問題總結(jié)

    Java中i++的一些問題總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java中i++的一些問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論