Java 获取两个List的交集和差集,以及应用场景操作

背景介绍

在实际项目中,特别是一些管理后台类的项目,会遇到底层数据是按照一对多关系的数据表存储的管理界面。列表页是一对多关系中一对应的数据列表,二级的详情页中是一对多关系中多对应的多条数据展示。通常二级页面是能够增、删、改数据的编辑页面,在点击保存提交数据后,服务器端需要插入新增的数据,删除要删除的数据,更新改变的数据。

例如,在汽车电商领域,如果要实现一辆车型在不同省份有不同的价格行情,就需要有一个车价管理的后台管理界面。每辆车对应的详情界面管理各省价格行情,增加该车在某个省份的行情,或者更新某个省份的行情,或者该车暂时去除某个省份的行情等功能,需要服务器端保证正确地数据存储。

交集:指的是两个List对象中都有的元素。

差集:指的是一个List对象中有,而另一个List对象中没有的元素。

转化为一般问题

在车价管理的车辆详情页面点击保存各省行情按钮后,请求会传送一组数据到服务端,服务端把这组数据保存到一个List对象中。然后从数据库中获取该车型之前的各省行情数据并保存到List对象中,那么怎么找出哪些数据是要新增的,哪些数据是要删除的,又有哪些数据是要更新的呢?

如果客户端传送的数据中有的省份行情数据,而数据库中没有该省行情数据记录,则这些数据是要插入数据库中的。如果客户端传送的数据有的省份行情数据,数据库中也有改省的行情数据,则这些数据是要更新的数据。如果数据库中有的省份数据,而客户端传送的数据中没有改省份数据,则这些数据是要删除的。

经过上述分析,不难发现就是找出两个List对象的交集和差集。例如,a为客户端传送的数据List对象,b为从数据库中获取的List对象。 a中有的元素,而b中没有的元素就是要插入数据库中的数据,即a与b的差集。a和b共有的元素就是要更新的数据,即a与b的交集。b中有的元素,a中没有的就是要删除的数据,即b与a的差集。

程序代码

程序的大致思路是:利用LinkedHashMap key值的唯一性和顺序存储的特性,把provinceId作为key值,先用一个map添加一个List元素,然后再去比较另一个List对象中的元素,找出provinceId相同的对象和只有b中才有的对象。map中去除相同的key值的对象,剩余的就是a中独有的元素。

各省行情类:

public class CarProvinceMarket {
  private Integer id;
  private Integer carId;
  private Integer provinceId;
  private Double price;
  private Integer createdBy;

  public Integer getCreatedBy() {
    return createdBy;
  }

  public void setCreatedBy(Integer createdBy) {
    this.createdBy = createdBy;
  }

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public Integer getCarId() {
    return carId;
  }

  public void setCarId(Integer carId) {
    this.carId = carId;
  }

  public Integer getProvinceId() {
    return provinceId;
  }

  public void setProvinceId(Integer provinceId) {
    this.provinceId = provinceId;
  }

  public Double getPrice() {
    return price;
  }

  public void setPrice(Double price) {
    this.price = price;
  }
}

求两个List对象交集、差集:

public class ListOperation {
  public static void sameAndDifferentOperation(List<CarProvinceMarket> a, List<CarProvinceMarket> b, List<CarProvinceMarket> sameItems,
                         List<CarProvinceMarket> onlyAItems, List<CarProvinceMarket> onlyBItems){

    if (a.isEmpty() && b.isEmpty()){
      return;
    }

    LinkedHashMap<Integer, CarProvinceMarket> map = new LinkedHashMap<>();
    LinkedHashMap<Integer, CarProvinceMarket> sameMap = new LinkedHashMap<>();
    LinkedHashMap<Integer, CarProvinceMarket> onlyBMap = new LinkedHashMap<>();
    for (CarProvinceMarket item: a){
      map.put(item.getProvinceId(), item);
    }

    for (CarProvinceMarket item: b){
      if (map.containsKey(item.getProvinceId())){

        //如果要更新a中的记录,则要更新map中的元素,并添加到sameMap
        CarProvinceMarket carProvinceMarket = map.get(item.getProvinceId());
        carProvinceMarket.setPrice(100000d);
        sameMap.put(item.getProvinceId(), carProvinceMarket);
      }else {
        //新建的元素,需要设置相关成员变量
        item.setCreatedBy(4);
        onlyBMap.put(item.getProvinceId(),item);
      }
    }

    sameItems.addAll(sameMap.values());
    onlyBItems.addAll(onlyBMap.values());

    for (CarProvinceMarket item: sameItems){
      map.remove(item.getProvinceId());
    }

    onlyAItems.addAll(map.values());

  }

  public static void main(String [] args){
    ArrayList<CarProvinceMarket> aCarProMar = new ArrayList<>();
    ArrayList<CarProvinceMarket> bCarProMar = new ArrayList<>();
    for (int i=0; i<1000000; i++){
      CarProvinceMarket aCar = new CarProvinceMarket();
      aCar.setProvinceId((i + 1)/2);
      aCarProMar.add(aCar);
      CarProvinceMarket bCar = new CarProvinceMarket();
      bCar.setProvinceId((i + 2)/2);
      bCarProMar.add(bCar);
    }

    LinkedList<CarProvinceMarket> sameItems = new LinkedList<>();
    LinkedList<CarProvinceMarket> onlyAItems = new LinkedList<>();
    LinkedList<CarProvinceMarket> onlyBItems = new LinkedList<>();

    Long start = System.currentTimeMillis();
    sameAndDifferentOperation(aCarProMar, bCarProMar, sameItems, onlyAItems, onlyBItems);
    System.out.println("time = " + (System.currentTimeMillis() - start));

  }
}

总结

在开发过程中,遇到问题要找出问题的一般性,转化概念,理解本质,方能解决问题。

代码链接: github

以上这篇Java 获取两个List的交集和差集,以及应用场景操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • IntelliJ IDEA里找不到javax.servlet的jar包的解决方法

    今天在复习Java Web时,因为初次使用 IntelliJ IDEA 中, 当使用javax.servlet包下的类时(例:javax.servlet.http.HttpServletRequest), 你会发现在IntelliJ IDEA里无法成功编译这个程序. 问题解决: 办法1:使用Project Structure 在弹出的窗口中选择tomcat所在的目录,进入里面的lib目录,寻找servlet-api.jar这个jar包(如果JSP页面也有相关的JavaWeb对象,则还要寻找jsp

  • 解决dubbo错误ip及ip乱入问题的方法

    问题 在本地启动dubbo时,服务注册在本地的zookeeper ,但是注册IP却不是本地的iP.产生问题,导致consumer 找不到provider ,访问不了服务. 例如 本地IP为 10.0.0.1 ,但是zookeeper上的注册ip 可能是 196.168.0.1 产生原因,随机产生,可能是你重启一下机器,或者电脑小智一段时间就会发生. 报错类似 com.alibaba.dubbo.remoting.RemotingException: client(url: dubbo://100

  • 如何解决IDEA使用Tomcat控制台中文出现乱码问题

    如下图所示,Intellij IDEA显示中文为乱码, 根据Intellij IDEA控制台输出,Tomcat Log出现乱码,因此可以将问题定位到Tomcat上,具体解决方法: 第一步:打开Tomcat安装位置,找到:conf下的logging.properties文件,然后右击使用文本编辑器打开. 第二步:把这五个UTF-8都改为:GBK 改好后如下图所示. 之后重启tomcat后在看控制台输出,中文就没有乱码了,成功解决! 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支

  • 为什么程序中突然多了 200 个 Dubbo-thread 线程的说明

    背景 在某次查看程序线程堆栈信息时,偶然发现有 200 个 Dubbo-thread 线程,而且大部分都处于 WAITING 状态,如下所示: "Dubbo-thread-200" #160932 daemon prio=5 os_prio=0 tid=0x00007f5af9b54800 nid=0x79a6 waiting on condition [0x00007f5a9acd5000] java.lang.Thread.State: WAITING (parking) at s

  • java 较大数据量取差集,list.removeAll性能优化详解

    今天在优化项目中的考勤同步功能时遇到将考勤机中的数据同步到数据库, 两边都是几万条数据的样子,老代码的做法差不多半个小时,优化后我本机差不多40秒,服务器速度会更加理想. 两个数据集取差集首先想到的方法便是List.removeAll方法,但是实验发现jdk自带的List.removeAll效率很低 List.removeAll效率低原因: List.removeAll效率低和list集合本身的特点有关 : List底层数据结构是数组,查询快,增删慢 1.List.contains()效率没有h

  • Java 获取两个List的交集和差集,以及应用场景操作

    背景介绍 在实际项目中,特别是一些管理后台类的项目,会遇到底层数据是按照一对多关系的数据表存储的管理界面.列表页是一对多关系中一对应的数据列表,二级的详情页中是一对多关系中多对应的多条数据展示.通常二级页面是能够增.删.改数据的编辑页面,在点击保存提交数据后,服务器端需要插入新增的数据,删除要删除的数据,更新改变的数据. 例如,在汽车电商领域,如果要实现一辆车型在不同省份有不同的价格行情,就需要有一个车价管理的后台管理界面.每辆车对应的详情界面管理各省价格行情,增加该车在某个省份的行情,或者更新

  • mysql 如何获取两个集合的交集/差集/并集

    mysql的常见场景,获取两个数据集的交集和差集 步骤 1.两个集合的结构要一致,对应的字段数,字段类型 2.将两个集合用 UNION ALL 关键字合并,这里的结果是有重复的所有集 3.将上面的所有集 GROUP BY id 4.最后 HAVING COUNT(id)=1,等于1的意思是只出现了一次,所以这个是差集,如果等于2,那么就是交集 代码演示 差集 下面的sql有明显的问题,不过这个只是一个示意, 从一个表中查询不需要用到交集和差集,条件可以合并在一起直接查询出来的.能明白意思就好 下

  • java获取两个数组中不同数据的方法

    本文实例讲述了java获取两个数组中不同数据的方法.分享给大家供大家参考.具体实现方法如下: public static <T> List<T> compare(T[] t1, T[] t2) { List<T> list1 = Arrays.asList(t1); List<T> list2 = new ArrayList<T>(); for (T t : t2) { if (!list1.contains(t)) { list2.add(t)

  • Java获取两个字符串中最大相同子串的方法

    "abcwerthelloyuiodef" "cvhellobnm" 思路: 1,将短的那个子串按照长度递减的方式获取到. 2,将每获取到的子串去长串中判断是否包含,如果包含,已经找到! class StringTest3 { public static String getMaxSubString(String s1,String s2) { String max = "",min = ""; max = (s1.lengt

  • JS计算两个数组的交集、差集、并集、补集(多种实现方式)

    方法一:最普遍的做法 使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本.也不用引入其他第三方库. 1,直接使用 filter.concat 来计算 var a = [1,2,3,4,5] var b = [2,4,6,8,10] //交集 var c = a.filter(function(v){ return b.indexOf(v) > -1 }) //差集 var d = a.filter(function(v){ return b.index

  • Pandas中两个dataframe的交集和差集的示例代码

    创建测试数据: import pandas as pd import numpy as np #Create a DataFrame df1 = { 'Subject':['semester1','semester2','semester3','semester4','semester1', 'semester2','semester3'], 'Score':[62,47,55,74,31,77,85]} df2 = { 'Subject':['semester1','semester2','s

  • Oracle 两个逗号分割的字符串,获取交集、差集(sql实现过程解析)

    Oracle数据库的两个字段值为逗号分割的字符串,例如:字段A值为"1,2,3,5",字段B为"2". 想获取两个字段的交集(相同值)2,获取两个字段的差集(差异值)1,3,5. 一.最终实现的sql语句 1.获取交集(相同值): select regexp_substr(id, '[^,]+', 1, rownum) id from (select '1,2,3,5' id from dual) connect by rownum <= length(reg

  • java 获取mac地址的两种方法(推荐)

    我在网上找了一下获取mac地址的方法,找了两种比较不太一样的方法. 第一种 public static void main(String[] args) throws Exception { InetAddress ia = InetAddress.getLocalHost(); System.out.println(getMACAddress(ia)); } private static String getMACAddress(InetAddress ia) throws Exception

  • java取两个字符串的最大交集

    本文实例讲述了java取两个字符串的最大交集的实现方法,分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: package com.itheima.net; public class Game13 {     public static void main(String[] args)     {         String s1 = "135adbfg67";         String s2 = "125dbf59";         Strin

  • JavaScript获取两个数组交集的方法

    本文实例讲述了JavaScript获取两个数组交集的方法.分享给大家供大家参考.具体如下: 这里传入的数组必须是已经排过序的 /* finds the intersection of * two arrays in a simple fashion. * * PARAMS * a - first array, must already be sorted * b - second array, must already be sorted * * NOTES * * Should have O(

随机推荐