jsonobject转list集合_怎样优雅的操作集合,CollectionUtils工具类正确使用姿势

点击上方"码之初"关注,···选择"设为星标"

与精品技术文章不期而遇

来源:cnblogs.com/qdhxhz/p/10787130.html

这篇讲的CollectionUtils工具类是在apache下的, 而不是springframework下的CollectionUtils。

个人觉得CollectionUtils在真实项目中,可以使你的代码更加简洁和安全。

所以需要倒入相关jar包,目前从maven找到最新jar包如下:

    <dependency><groupId>org.apache.commonsgroupId><artifactId>commons-collections4artifactId><version>4.3version>dependency>

一、API常用方法

 /**         * 1、除非元素为null,否则向集合添加元素         */        CollectionUtils.addIgnoreNull(personList,null);        /**         * 2、将两个已排序的集合a和b合并为一个已排序的列表,以便保留元素的自然顺序         */        CollectionUtils.collate(Iterable extends O> a, Iterable extends O> b)        /**         * 3、将两个已排序的集合a和b合并到一个已排序的列表中,以便保留根据Comparator c的元素顺序。         */        CollectionUtils.collate(Iterable extends O> a, Iterable extends O> b, Comparator super O> c)        /**         * 4、返回该个集合中是否含有至少有一个元素         */        CollectionUtils.containsAny(Collection> coll1, T... coll2)        /**         * 5、如果参数是null,则返回不可变的空集合,否则返回参数本身。(很实用 ,最终返回List EMPTY_LIST = new EmptyList<>())         */        CollectionUtils.emptyIfNull(Collection collection)        /**         * 6、空安全检查指定的集合是否为空         */        CollectionUtils.isEmpty(Collection> coll)        /**         * 7、 空安全检查指定的集合是否为空。         */        CollectionUtils.isNotEmpty(Collection> coll)        /**         * 8、反转给定数组的顺序。         */        CollectionUtils.reverseArray(Object[] array);        /**         * 9、差集         */        CollectionUtils.subtract(Iterable extends O> a, Iterable extends O> b)        /**         * 10、并集         */        CollectionUtils.union(Iterable extends O> a, Iterable extends O> b)        /**         * 11、交集         */        CollectionUtils.intersection(Collection a, Collection b)        /**         *12、 交集的补集(析取)         */        CollectionUtils.disjunction(Collection a, Collection b)

二、非对象集合交、并、差处理

对于集合取交集、并集的处理其实有很多种方式,这里就介绍3种

  • 第一种 是CollectionUtils工具类

  • 第二种 是List自带方法

  • 第三种 是JDK1.8 stream 新特性

1、CollectionUtils工具类

下面对于基本数据(包扩String)类型中的集合进行demo示例。

public static void main(String[] args) {        String[] arrayA = new String[] { "1", "2", "3", "4"};        String[] arrayB = new String[] { "3", "4", "5", "6" };        List<String> listA = Arrays.asList(arrayA);        List<String> listB = Arrays.asList(arrayB);        //1、并集 union        System.out.println(CollectionUtils.union(listA, listB));        //输出: [1, 2, 3, 4, 5, 6]        //2、交集 intersection        System.out.println(CollectionUtils.intersection(listA, listB));        //输出:[3, 4]        //3、交集的补集(析取)disjunction        System.out.println(CollectionUtils.disjunction(listA, listB));        //输出:[1, 2, 5, 6]        //4、差集(扣除)        System.out.println(CollectionUtils.subtract(listA, listB));        //输出:[1, 2]    }

2、List自带方法

public static void main(String[] args) {        String[] arrayA = new String[] { "1", "2", "3", "4"};        String[] arrayB = new String[] { "3", "4", "5", "6" };        List<String> listA = Arrays.asList(arrayA);        List<String> listB = Arrays.asList(arrayB);        //1、交集        List<String>  jiaoList = new ArrayList<>(listA);        jiaoList.retainAll(listB);        System.out.println(jiaoList);        //输出:[3, 4]       //2、差集        List<String>  chaList = new ArrayList<>(listA);        chaList.removeAll(listB);        System.out.println(chaList);        //输出:[1, 2]        //3、并集 (先做差集再做添加所有)        List<String>  bingList = new ArrayList<>(listA);        bingList.removeAll(listB); // bingList为 [1, 2]        bingList.addAll(listB);  //添加[3,4,5,6]        System.out.println(bingList);        //输出:[1, 2, 3, 4, 5, 6]    }

注意 : intersection和retainAll的差别

要注意的是它们的返回类型是不一样的,intersection返回的是一个新的List集合,而retainAll返回是Bollean类型那就说明retainAll方法是对原有集合进行处理再返回原有集合,会改变原有集合中的内容。

个人观点:1、从性能角度来考虑的话,List自带会高点,因为它不用再创建新的集合。2、需要注意的是:因为retainAll因为会改变原有集合,所以该集合需要多次使用就不适合用retainAll。

注意: Arrays.asList将数组转集合不能进行add和remove操作。

原因:调用Arrays.asList()生产的List的add、remove方法时报异常,这是由Arrays.asList() 返回的市Arrays的内部类ArrayList, 而不是java.util.ArrayList。Arrays的内部类ArrayList和java.util.ArrayList都是继承AbstractList,remove、add等方法AbstractList中是默认throw UnsupportedOperationException而且不作任何操作。java.util.ArrayList重新了这些方法而Arrays的内部类ArrayList没有重新,所以会抛出异常。

所以正确做法如下

        String[] array = {"1","2","3","4","5"};
List list = Arrays.asList(array);
List arrList = new ArrayList(list);
arrList.add("6");

3、JDK1.8 stream 新特性

public static void main(String[] args) {        String[] arrayA = new String[] { "1", "2", "3", "4"};        String[] arrayB = new String[] { "3", "4", "5", "6" };        List<String> listA = Arrays.asList(arrayA);        List<String> listB = Arrays.asList(arrayB);        // 交集        List<String> intersection = listA.stream().filter(item -> listB.contains(item)).collect(toList());        System.out.println(intersection);        //输出:[3, 4]        // 差集 (list1 - list2)        List<String> reduceList = listA.stream().filter(item -> !listB.contains(item)).collect(toList());        System.out.println(reduceList);        //输出:[1, 2]        // 并集 (新建集合:1、是因为不影响原始集合。2、Arrays.asList不能add和remove操作。        List<String> listAll = listA.parallelStream().collect(toList());        List<String> listAll2 = listB.parallelStream().collect(toList());        listAll.addAll(listAll2);        System.out.println(listAll);        //输出:[1, 2, 3, 4, 3, 4, 5, 6]        // 去重并集        List<String> list =new ArrayList<>(listA);        list.addAll(listB);        List<String> listAllDistinct = list.stream().distinct().collect(toList());        System.out.println(listAllDistinct);        //输出:[1, 2, 3, 4, 5, 6]    }

总结 :这三种我还是最喜欢第一种方式,因为第二种还需要确定该集合是否被多次调用。第三种可读性不高。

三、对象集合交、并、差处理

因为对象的equels比较是比较两个对象的内存地址,所以除非是同一对象,否则equel返回永远是false。

但我们实际开发中 在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了,所以这个时候我们需要重写equals方法。

说明 :String为什么可以使用equels方法为什么只要字符串相等就为true,那是因为String类重写了equal和hashCode方法,比较的是值。

1、Person对象

public class Person {    private String name;    private Integer age;    public Person(String name, Integer age) {        this.name = name;        this.age = age;    }    /**     * 为什么重写equals方法一定要重写hashCode方法下面也会讲     */    @Override    public int hashCode() {        String result = name + age;        return result.hashCode();    }    /**     * 重写 equals 方法 根据name和age都相同那么对象就默认相同     */    @Override    public boolean equals(Object obj) {        Person u = (Person) obj;        return this.getName().equals(u.getName()) && (this.age.equals(u.getAge()));    }    /**     * 重写 toString 方法     */    @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }  }

2、测试

这里根据name和age都相同那么就默认相同对象。

public static void main(String[] args) {        List personList = Lists.newArrayList();        Person person1 = new Person("小小",3);        Person person2 = new Person("中中",4);        personList.add(person1);        personList.add(person2);        List person1List = Lists.newArrayList();        Person person3 = new Person("中中",4);        Person person4 = new Person("大大",5);        person1List.add(person3);        person1List.add(person4);        /**         * 1、差集         */        System.out.println(CollectionUtils.subtract(personList, person1List));        //输出:[Person{name='小小', age=3}]        /**         * 2、并集         */        System.out.println(CollectionUtils.union(personList, person1List));        //输出:[Person{name='小小', age=3}, Person{name='中中', age=4}, Person{name='大大', age=5}]        /**         * 3、交集         */        System.out.println(CollectionUtils.intersection(personList, person1List));        //输出:[Person{name='中中', age=4}]        /**         * 4、交集的补集(析取)         */        System.out.println(CollectionUtils.disjunction(personList, person1List));        //输出:[Person{name='小小', age=3}, Person{name='大大', age=5}]    }

其它两种方式就不在测了,因为都一样。

四、为什么重写equels方法一定要重写hashCode方法

1、源码

其实上面的Person类我可以只重写equels方法而不写hashCode方法,一样能达到上面的效果。但为什么还是建议写上呢?官方的说法是:对象的equals方法被重写,那么对象的hashCode()也尽量重写

重写equals()方法就必须重写hashCode()方法的原因,从源头Object类讲起就更好理解了。

先来看Object关于hashCode()和equals()的源码:

  public native int hashCode();public boolean equals(Object obj) {return (this == obj);
}

光从代码中我们可以知道,hashCode()方法是一个本地native方法,返回的是对象引用中存储的对象的内存地址。而equals方法是利用==来比较的也是对象的内存地址。从上边我们可以看出,hashCode方法和equals方法是一致的。还有最关键的一点,我们来看Object类中关于hashCode()方法的注释:

  1. 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。

  2. 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。

  3. 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。 但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

整理 : hashCode()和equals()保持一致,如果equals方法返回true,那么两个对象的hasCode()返回值必须一样。如果equals方法返回false,hashcode可以不一样,但是这样不利于哈希表的性能,一般我们也不要这样做。

假设两个对象,重写了其equals方法,其相等条件是某属性相等,就返回true。如果不重写hashcode方法,其返回的依然是两个对象的内存地址值,必然不相等。这就出现了equals方法相等,但是hashcode不相等的情况。这不符合hashcode的规则。

2、HashSet和Map集合类型

重写equals()方法就必须重写hashCode()方法主要是针对HashSet和Map集合类型,而对于List集合倒没什么影响。

原因:在向HashSet集合中存入一个元素时,HashSet会调用该对象(存入对象)的hashCode()方法来得到该对象的hashCode()值,然后根据该hashCode值决定该对象在HashSet中存储的位置。简单的说:HashSet集合判断两个元素相等的标准是:两个对象通过equals()方法比较相等,并且两个对象的HashCode()方法返回值也相等。如果两个元素通过equals()方法比较返回true,但是它们的hashCode()方法返回值不同,HashSet会把它们存储在不同的位置,依然可以添加成功。

这就是问题所在:就是如果你只重写equals()方法,而不重写hashCode(),如果equals()为true,而它们的hashCode()方法返回值肯定不一样,因为它们都不是同一对象所以内存地址肯定不一样,所以它还是添加成功了,那么其实你写的equals()方法根本没啥软用。

3、代码示例

1、People类

重写equals方法,但并没有hashCode方法。

public class People {    private String name;    private Integer age;    public People(String name, Integer age) {        this.name = name;        this.age = age;    }    /**     * 重写 equals 方法     */    @Override    public boolean equals(Object obj) {        People u = (People) obj;        return this.getName().equals(u.getName()) && (this.age.equals(u.getAge()));    }    /**     * 重写 toString 方法     */    @Override    public String toString() {        return "People{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}

2、实现类

public static void main(String[] args) {        HashSet hashSet = Sets.newHashSet();        People people1 = new People("小小",3);        People people2 = new People("中中",4);        People people3 = new People("中中",4);        People people4 = new People("大大",5);        hashSet.add(people1);        hashSet.add(people2);        hashSet.add(people3);        hashSet.add(people4);        System.out.println(hashSet);        //输出:[People{name='小小', age=3}, People{name='中中', age=4}, People{name='大大', age=5}, People{name='中中', age=4}]    }

很明显,我重写了equals方法,那么people2和people3的equals应该相同,所以不能放入HashSet,但它们的hashCode()方法返回不同,所以导致同样能放入HashSet。

重点:对于Set集合必须要同时重写这两个方法,要不然Set的特性就被破坏了。

a1fa1f95e3a15d2596fe329b0d0c7187.png

f8e99da2577286ec4ff923ec7ade4af8.png

71d7f2f31e81124695a8b900fe5ecf22.png

好文,点个在看吧cd156d8c74c3ffe44d8c4661eb0509cf.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[c#基础]使用抽象工厂实现三层

引言 昨天加了一天班&#xff0c;今天闲来无事&#xff0c;就在想如何将之前的三层和最近一直在学的设计模式给联系在一起&#xff0c;然后就动手弄了个下面的小demo。 项目结构 项目各个层实现 Wolfy.Model层中有一个抽象类BaseModel.cs&#xff0c;User.cs是用户实体类&#…

场效应管原理_场效应管——不就是一个电控开关?

管在mpn中&#xff0c;它的长相和我们常面讲的三极管非常像&#xff0c;所以有不少修朋友好长时间还分不清楚&#xff0c;统一的把这些长相相同的三极管、场效应管、双二极管、还有各种稳压IC统统称作“三个脚的管管”&#xff0c;呵呵&#xff0c;如果这样麻木不分的话&#x…

三次握手面试题java_java面试题三次握手和四次挥手-嗨客网

题目对 tcp 了解吗&#xff1f;讲讲它的三次握手和四次挥手&#xff1f;为什么需要三次握手&#xff0c;为什么需要四次挥手。答案三次握手第一次握手&#xff1a;客户端向服务器发送连接请求&#xff0c;这个时候报文首部中的同步为 SYN 1&#xff0c;同时生成一个随机序列号…

运维经验分享(三)-- 解决Ubuntu下crontab不能正确执行脚本的问题

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://dgd2010.blog.51cto.com/1539422/1676490 运维经验分享作为一个专题&#xff0c;目前共7篇文章 《运维经验分享&#xff08;一&#xff0…

一个jsp能取到父类jsp的值吗_「Javaweb」ssm整合权限控制框架shiro,你知道怎么做吗?...

为美好而努力——羊羽科技说。最近在开发自己的网站&#xff0c;需要权限控制功能&#xff0c;在网上找了一下&#xff0c;找到了我接下来要介绍的shiro框架。shiro框架是Apache公司维护的开源产品之一&#xff0c;其官网对其的简介是这样的&#xff1a;shiro官网简介翻译过来就…

php设置用户头像,PHP针对多用户实现更换头像功能

一个网站&#xff0c;其实说白了就是某几个特定功能的组合&#xff0c;而更换用户头像就在这些功能之中。今天就来做个测试&#xff0c;针对不同的用户&#xff0c;实现头像上传功能。先给大家展示下成品效果图&#xff1a;思路针对不同的用户上传头像&#xff0c;我们要为每一…

执行计划中cpu耗时_面试被问怎么排查遇到的系统CPU飙高和频繁GC,到底该怎么回答?...

处理过线上问题的同学基本上都会遇到系统突然运行缓慢&#xff0c;CPU 100%&#xff0c;以及Full GC次数过多的问题。当然&#xff0c;这些问题的最终导致的直观现象就是系统运行缓慢&#xff0c;并且有大量的报警。本文主要针对系统运行缓慢这一问题&#xff0c;提供该问题的排…

可视化数据包分析工具-CapAnalysis

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://chenguang.blog.51cto.com/350944/1325742 可视化数据包分析工具-CapAnalysis 我们知道&#xff0c;Xplico是一个从pcap文件中解析出IP流…

网易云歌单添加到php,给自己的网站添加网易云音乐歌单吧^ ^

这个是怎么实现的&#xff1f;一起来看看吧APlayer首先我们需要一个音频播放器&#xff0c;这里我用到了APlayer&#xff0c;这是由bilibili前端大神DIYgod开源的播放器&#xff0c;有兴趣的可以去TA的主页看看&#xff0c;非常惊艳&#xff0c;这里我就不多说了我们看一下APla…

百度应用部署秘籍

2019独角兽企业重金招聘Python工程师标准>>> 【背景介绍】 传统PaaS采用sandbox实现app间的资源安全隔离&#xff0c;sandbox需要对运行环境和编程语言进行底层的功能限制&#xff0c;例如&#xff1a;禁止创建进程和线程&#xff0c;禁止部分系统调用&#xff0c;禁…

java8新特性_JAVA8十大新特性详解

一、接口的默认方法Java 8允许我们给接口添加一个非抽象的方法实现&#xff0c;只需要使用 default关键字即可&#xff0c;这个特征又叫做扩展方法&#xff0c;示例如下&#xff1a;interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sq…

spark1.6.1 on yarn搭建部署

注&#xff1a;本文是建立在hadoop已经搭建完成的基础上进行的。 Apache Spark是一个分布式计算框架&#xff0c;旨在简化运行于计算机集群上的并行程序的编写。该框架对资源调度&#xff0c;任务的提交、执行和跟踪&#xff0c;节点间的通信以及数据并行处理的内在底层操作都进…

主线程是如何向子线程传递数据的?_c++ 利用thread创建线程

用进行多线程开发小时候&#xff0c;老师总是教育我们上课要专心&#xff0c;“一心不可二用”。可是CPU这个不听话的“熊孩子”偏偏却在一个芯片中加入了两个甚至多个运算核心&#xff0c;想要一“芯”二用。从硬件厂商的角度&#xff0c;通过增加CPU的运算核心&#xff0c;突…

php多维数组交集,求数组差/交集函数-php数组函数(二)

求数组差集函数函数只检查了多维数组中的一维。可以用 array_diff($array1[0], $array2[0]) 检查更深的维度。u&#xff1a;自定义函数比较&#xff0c;a(association)&#xff1a;同时比较键和值。自定义函数callable $value_compare_func必须返回一个小于零&#xff0c;等于零…

正则过滤符号_多角度理解正则项

过拟合和欠拟合什么是过拟合和欠拟合过拟合&#xff1a;模型在训练集上效果好&#xff0c;在测试集上效果差欠拟合&#xff1a;在训练集上效果就不好产生过拟合的原因参数太多&#xff0c;模型复杂度太高数据量少&#xff0c;训练轮次过多样本中噪声较大&#xff0c;模型拟合了…

PHP页面中嵌套go语言,go语言嵌套类型的使用细节

1. 定义在Go语言中&#xff0c;嵌套类型是将已有的类型直接声明在新的结构类型里。被嵌入的类型被称为新的外部类型的内部类型。通过嵌入类型&#xff0c;与内部类型相关的成员变量会提升到外部类型上。就好像这些成员变量直接声明在外部类型一样。如下图所示&#xff1a;外部类…

jvm内存模型_JVM内存模型的相关概念

1.前言Android的虚拟机是根据移动设备的特点基于Java虚拟机(JVM)改进而来&#xff0c;虽然没有保留规范&#xff0c;但作为Java语言的使用者&#xff0c;了解一下JVM的规范还是有必要的。2.JVM内存模型JVM在执行Java程序时&#xff0c;会把它管理的内存划分为若干个的区域&…

LNMP/LEMP(PHP7.0.04+mysql5.7.12+nginx1.10.0)

预览:Installing Nginx with PHP 7 and MySQL 5.7 (LEMP) on Ubuntu 16.04 LTSThis tutorial exists for these OS versionsUbuntu 15.10 (Wily Werewolf)Ubuntu 14.04 LTS (Trusty Tahr)Ubuntu 13.04 (Raring Ringtail)Ubuntu 12.10 (Quantal Quetzal)Ubuntu 12.04 LTS (Preci…

length函数的头文件_Framebuffer 应用编程中涉及的 API 函数

本节程序的目的是&#xff1a;打开 LCD 设备节点&#xff0c;获取分辨率等参数&#xff0c;映射 Framebuffer&#xff0c;最后实现描点函数。5.2.1 open 函数在 Ubuntu 中执行“man 2 open”&#xff0c;可以看到 open 函数的说明&#xff1a;头文件&#xff1a;#include <s…

xib中UIScrollView固定底部内容

UIScrollView的高度在xib中设置 需要固定的部分用代码添加: UIImageView *textLogo [[UIImageView alloc] initWithFrame:CGRectMake((kMSScreenWith - 153)/2, (kMSScreenHeight - 118 > 549 ? kMSScreenHeight : 667) - 173, 153, 35)]; textLogo.image [UIImage image…