最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Java獲取List交集數(shù)據(jù)的實(shí)現(xiàn)方案小結(jié)

 更新時(shí)間:2024年03月18日 09:15:30   作者:洛小豆  
今天遇到一個(gè)小需求,當(dāng)用戶上傳了一個(gè)關(guān)于用戶數(shù)據(jù)的列表,我們需要將其與數(shù)據(jù)庫(kù)中已有的用戶數(shù)據(jù)進(jìn)行比較,所以本文給大家介紹了使用Java獲取List交集數(shù)據(jù)的實(shí)現(xiàn)方案小結(jié),文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下

需求背景

今天遇到一個(gè)小需求,當(dāng)用戶上傳了一個(gè)關(guān)于用戶數(shù)據(jù)的列表,我們需要將其與數(shù)據(jù)庫(kù)中已有的用戶數(shù)據(jù)進(jìn)行比較。假設(shè)數(shù)據(jù)庫(kù)中的用戶數(shù)據(jù)存儲(chǔ)在集合A中,而用戶上傳的數(shù)據(jù)存儲(chǔ)在集合B中。我們需要確定集合B中有多少數(shù)據(jù)在集合A中,以及有多少數(shù)據(jù)不在集合A中,并記錄這些信息到日志中。那么,我們應(yīng)該如何處理這個(gè)需求呢?

解決方案

一、如何查找兩個(gè)集合的重復(fù)數(shù)據(jù)?

如果兩個(gè)集合中存放的都是String類(lèi)型數(shù)據(jù),那這個(gè)操作就會(huì)簡(jiǎn)單很多,這里先初始化一下兩個(gè)集合的數(shù)據(jù)作為參考,接著給大家一些參考的方法

List<String> listA = Arrays.asList("Apple", "Banana", "Cherry", "Date"); 
List<String> listB = Arrays.asList("Banana", "Date", "Fig", "Grape");

1、使用retainAll()

retainAll()方法會(huì)修改原始的集合A,使其只包含同時(shí)存在于集合A和集合B中的元素。

// 直接在集合A上使用retainAll()方法,它會(huì)保留只存在于集合A和集合B中的元素 
listA.retainAll(listB); 
System.out.println("Elements in both lists: " + listA);

2、使用stream()和filter()

// 使用stream()方法和filter()方法找到兩個(gè)集合的交集
List<String> intersection = listA.stream()
    .filter(listB::contains)
    .collect(Collectors.toList());

System.out.println("Elements in both lists: " + intersection);

3、使用stream()和anyMatch()

// 使用anyMatch()檢查集合A中的每個(gè)元素是否在集合B中
List<String> intersection = listA.stream()
    .filter(element -> listB.anyMatch(b -> b.equals(element)))
    .collect(Collectors.toList());

System.out.println("Elements in both lists: " + intersection);

上面的代碼使用 listB.anyMatch(b -> b.equals(element))。對(duì)于 listA 中的每個(gè)元素,它創(chuàng)建一個(gè)新的流來(lái)遍歷 listB 的所有元素,直到找到相等的元素或遍歷完所有元素。每次調(diào)用 anyMatch 都會(huì)遍歷 listB,這同樣是一個(gè) O(n) 操作;但它在內(nèi)部使用了流,這會(huì)增加額外的開(kāi)銷(xiāo)。

4、使用Collection的intersection()

如果你想要獲取兩個(gè)集合的交集,可以使用Collection接口提供的intersection()方法:

Set<String> intersectionSet = new HashSet<>(listA);
intersectionSet.retainAll(listB);

List<String> intersection = new ArrayList<>(intersectionSet);
System.out.println("Elements in both lists: " + intersection);

5、查詢(xún)集合B中不與集合A重合的數(shù)據(jù)

這時(shí)候如果要查詢(xún)包含集合B中不與集合A重合的數(shù)據(jù),我們只要簡(jiǎn)單修改一下上面的方法即可,我們還是使用Java 8的Stream API來(lái)創(chuàng)建一個(gè)新的集合,這個(gè)集合包含集合B中獨(dú)有的元素。

// 使用Stream API找出集合B中不包含在集合A中的元素
List<String> uniqueInB = listB.stream()
    .filter(element -> !listA.contains(element))
    .collect(Collectors.toList());

// 打印集合B中不和集合A重合的數(shù)據(jù)
System.out.println("Elements in list B only: " + uniqueInB);

在數(shù)據(jù)量不大的情況下,使用Stream API的方法通常是足夠高效的,并且代碼簡(jiǎn)潔易讀。如果數(shù)據(jù)量非常大,您可能需要考慮其他方法,例如將集合轉(zhuǎn)換為HashSet以提高查找效率,或者使用并行流(parallel streams)來(lái)利用多核處理器。

二、假設(shè)集合A的數(shù)據(jù)更多,該如何優(yōu)化?

如果集合A的數(shù)據(jù)比集合B中的數(shù)據(jù)更多,為了提高效率,我們可以做一些調(diào)整。這里有兩個(gè)優(yōu)化點(diǎn):

  • 我們使用了listB::contains來(lái)檢查一個(gè)元素是否在集合B中。如果集合A更大,那么使用listA::contains可能會(huì)更高效,因?yàn)楸闅v較小的集合將減少必要的contains檢查次數(shù)。
  • .contains 方法的性能取決于被搜索的集合的類(lèi)型。對(duì)于ArrayListcontains 方法的時(shí)間復(fù)雜度是 O(n),它會(huì)遍歷整個(gè)列表來(lái)查找元素,而對(duì)于HashSet,時(shí)間復(fù)雜度是 O(1),因?yàn)樗褂霉1磉M(jìn)行查找。我們這時(shí)候就可以將集合A轉(zhuǎn)換為一個(gè)HashSet。

完整的示例代碼:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

// 假設(shè)集合A和集合B已經(jīng)初始化
List<String> listA = Arrays.asList("Apple", "Banana", "Cherry", "Date", "Fig", "Grape");
List<String> listB = Arrays.asList("Banana", "Date", "Fig");

// 將集合A轉(zhuǎn)換為HashSet,以提高查找效率
Set<String> setA = new HashSet<>(listA);

// 生成集合C,保存集合A和集合B的重合數(shù)據(jù)
List<String> listC = listB.stream()
    .filter(setA::contains) // 使用HashSet來(lái)檢查交集,提高效率
    .collect(Collectors.toList()); // 收集結(jié)果到一個(gè)新的列表

// 生成集合D,保存集合B中沒(méi)有和集合A重合的數(shù)據(jù)
List<String> listD = listB.stream()
    .filter(element -> !setA.contains(element)) // 使用HashSet來(lái)檢查差異,提高效率
    .collect(Collectors.toList()); // 收集結(jié)果到一個(gè)新的列表

// 打印結(jié)果
System.out.println("List C (common elements): " + listC);
System.out.println("List D (unique to list B): " + listD);

補(bǔ)充說(shuō)明:

如果集合A和集合B都是使用List實(shí)現(xiàn),那么兩種方法的時(shí)間復(fù)雜度在本質(zhì)上是相同的。每次調(diào)用contains方法時(shí),都會(huì)在另一個(gè)列表上進(jìn)行線性搜索,這意味著每次調(diào)用的時(shí)間復(fù)雜度都是O(n)。

對(duì)集合A中的每個(gè)元素調(diào)用listB::contains,如果集合A有n個(gè)元素,集合B有m個(gè)元素,那么總的時(shí)間復(fù)雜度就是O(n*m)。

對(duì)集合B中的每個(gè)元素調(diào)用listA::contains,同樣地,如果集合A有n個(gè)元素,集合B有m個(gè)元素,那么總的時(shí)間復(fù)雜度也是O(n*m)。

如果集合A遠(yuǎn)大于集合B,遍歷較小的集合B通常在實(shí)際應(yīng)用中效率更高,即使時(shí)間復(fù)雜度在理論上是相等的。這是因?yàn)檩^小的集合遍歷次數(shù)更少,從而減少了實(shí)際執(zhí)行的總步驟數(shù)。不過(guò),這種效率的差異只能在實(shí)際運(yùn)行時(shí)才能體現(xiàn)。

三、如果集合中存放的是對(duì)象,該如何操作?

通常情況下,我們不會(huì)在集合中存放字符串,都是放一些對(duì)象數(shù)據(jù),這時(shí)候該如何獲取呢?在這里我們定義一個(gè)Person作為示例,假設(shè)Person對(duì)象在nameage屬性都相同時(shí)被認(rèn)為是相等的。

在Java中使用contains方法來(lái)檢查一個(gè)集合是否包含某個(gè)對(duì)象時(shí),就需要重寫(xiě)對(duì)象的equalshashCode方法。這是因?yàn)?code>contains方法的實(shí)現(xiàn)依賴(lài)于equals方法來(lái)比較對(duì)象,而hashCode方法則用于快速查找和確定對(duì)象在散列數(shù)據(jù)結(jié)構(gòu)(如HashSetHashMap)中的位置。

equalshashCode方法之間有一個(gè)重要的一致性約定:

  • 如果兩個(gè)對(duì)象根據(jù)equals方法是相等的,那么它們的hashCode方法也必須返回相同的值。
  • 如果兩個(gè)對(duì)象的hashCode值不同,那么它們一定不相等(根據(jù)equals方法)。

這個(gè)約定對(duì)于HashSet、HashMap等集合的正確運(yùn)作至關(guān)重要。如果你只重寫(xiě)了equals方法而沒(méi)有重寫(xiě)hashCode方法,可能會(huì)導(dǎo)致集合的行為不符合預(yù)期,例如,即使兩個(gè)對(duì)象相等,HashSet也可能認(rèn)為它們是不同的對(duì)象并存儲(chǔ)兩個(gè)副本。

示例代碼

public class Person {
    private String name;
    private int age;

    // 構(gòu)造函數(shù)、getter和setter省略

    @Override
    public boolean equals(Object o) {
        if (this == o) return true; // 如果是同一個(gè)對(duì)象,直接返回true
        if (o == null || getClass() != o.getClass()) return false; // 如果對(duì)象為空或者類(lèi)類(lèi)型不一致,返回false

        Person person = (Person) o; // 向下轉(zhuǎn)型

        // 比較name和age屬性
        return Objects.equals(name, person.name) && age == person.age;
    }

    @Override
    public int hashCode() {
        // 使用31作為質(zhì)數(shù),可以減少哈希沖突
        int result = 17;
        result = 31 * result + Objects.hashCode(name); // 根據(jù)name計(jì)算哈希碼
        result = 31 * result + Integer.hashCode(age); // 根據(jù)age計(jì)算哈希碼
        return result;
    }
}

在這個(gè)實(shí)現(xiàn)中,equals方法首先檢查是否是同一個(gè)對(duì)象,然后檢查對(duì)象是否為空或者是否是不同的類(lèi)型。如果這些檢查都通過(guò)了,它會(huì)通過(guò)Objects.equals方法比較name屬性,并直接比較age屬性的值。

hashCode方法使用了一個(gè)固定的質(zhì)數(shù)(在這里是17)作為初始哈希碼。然后,它使用31作為乘數(shù)(31是一個(gè)質(zhì)數(shù),通常用于計(jì)算哈希碼,因?yàn)樗兄诒苊夤_突)。hashCode方法分別對(duì)nameage屬性調(diào)用Objects.hashCodeInteger.hashCode方法來(lái)計(jì)算它們的哈希碼,并將它們組合起來(lái)。

以上就是使用Java獲取List交集數(shù)據(jù)的實(shí)現(xiàn)方案小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java獲取List交集數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • @FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式

    @FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式

    這篇文章主要介紹了@FeignClient?實(shí)現(xiàn)簡(jiǎn)便http請(qǐng)求封裝方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot配置文件密碼加密的三種方案

    SpringBoot配置文件密碼加密的三種方案

    這篇文章主要介紹了SpringBoot配置文件密碼加密的三種方案,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-04-04
  • swagger注解@ApiModelProperty失效情況的解決

    swagger注解@ApiModelProperty失效情況的解決

    這篇文章主要介紹了swagger注解@ApiModelProperty失效情況的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Maven?繼承父工程時(shí)的relativePath標(biāo)簽詳細(xì)解析

    Maven?繼承父工程時(shí)的relativePath標(biāo)簽詳細(xì)解析

    這篇文章主要介紹了Maven?繼承父工程時(shí)的relativePath標(biāo)簽解析,通過(guò)本文學(xué)習(xí)你需要注意子模塊想要用父模塊pom中的版本,請(qǐng)注意配置relativePath屬性,需要的朋友可以參考下
    2022-12-12
  • 自定義BufferedReader的實(shí)例

    自定義BufferedReader的實(shí)例

    下面小編就為大家分享一篇自定義BufferedReader的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 老生常談spring?boot中的定時(shí)任務(wù)

    老生常談spring?boot中的定時(shí)任務(wù)

    SpringBoot中的定時(shí)任務(wù)主要通過(guò)@Scheduled注解以及SchedulingConfigurer接口實(shí)現(xiàn),本文給大家介紹spring?boot中的定時(shí)任務(wù),感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • 深入探索Java常量池

    深入探索Java常量池

    這篇文章主要介紹了深入探索Java常量池,涉及靜態(tài)常量池和運(yùn)行時(shí)常量池的介紹,常量池的好處,8種基本數(shù)據(jù)類(lèi)型的包裝類(lèi)和常量池等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • SpringBoot整合Dubbo框架,實(shí)現(xiàn)RPC服務(wù)遠(yuǎn)程調(diào)用

    SpringBoot整合Dubbo框架,實(shí)現(xiàn)RPC服務(wù)遠(yuǎn)程調(diào)用

    Dubbo是一款高性能、輕量級(jí)的開(kāi)源Java RPC框架,它提供了三大核心能力:面向接口的遠(yuǎn)程方法調(diào)用,智能容錯(cuò)和負(fù)載均衡,以及服務(wù)自動(dòng)注冊(cè)和發(fā)現(xiàn)。今天就來(lái)看下SpringBoot整合Dubbo框架的步驟
    2021-06-06
  • Java實(shí)現(xiàn)多數(shù)據(jù)源的幾種方式總結(jié)

    Java實(shí)現(xiàn)多數(shù)據(jù)源的幾種方式總結(jié)

    這篇文章主要給大家總結(jié)介紹了關(guān)于Java實(shí)現(xiàn)多數(shù)據(jù)源的幾種方式,最近項(xiàng)目中的工作流需要查詢(xún)多個(gè)數(shù)據(jù)源的數(shù)據(jù),數(shù)據(jù)源可能是不同種類(lèi)的,需要的朋友可以參考下
    2023-08-08
  • logback如何去掉DubboMonitor煩人的INFO日志

    logback如何去掉DubboMonitor煩人的INFO日志

    這篇文章主要介紹了logback如何去掉DubboMonitor煩人的INFO日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評(píng)論

稷山县| 石河子市| 马尔康县| 潜江市| 大洼县| 郎溪县| 永吉县| 阜平县| 嵩明县| 清新县| 永登县| 同德县| 玉树县| 玉山县| 开封县| 霍州市| 甘泉县| 桃园县| 景宁| 高阳县| 防城港市| 尼木县| 简阳市| 大港区| 台前县| 绥中县| 商水县| 阿克| 玉山县| 玉溪市| 舒兰市| 潼南县| 汝南县| 临潭县| 新河县| 尉氏县| 铜梁县| 萨嘎县| 台中市| 河池市| 涡阳县|