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,一经查实,立即删除!

相关文章

docx命令运行Java_使用Java将DOC文件转换为DOCX

7 个答案:答案 0 :(得分&#xff1a;3)// Open a document.Document doc new Document("input.doc");// Save document.doc.save("output.docx");请查看这在您的方案中是否有帮助。披露&#xff1a;我在Aspose担任开发人员传播者。答案 1 :(得分&#xff…

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

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

php 当前ip_php获取本机ip(远程IP地址)

例子&#xff0c;php获取用户IP地址。复制代码 代码示例:// 111111111111echo $_SERVER[REMOTE_ADDR];// 2222222222222function get_local_ip() {$preg "/\A((([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\.){3}(([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25…

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

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

解决phpMyAdmin在nginx+php-fpm模式下无法使用的问题

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://dgd2010.blog.51cto.com/1539422/1684839 昨天接到一个网友的问题&#xff0c;说yum安装nginxphp-fpmmysqlphpMyAdmin后&#xff0c;发现…

python库有什么用_Python程序员必知什么 常用的Python库有哪些

Python程序员必知什么&#xff1f;常用的Python库有哪些&#xff1f;Python有很多丰富而强大的库&#xff0c;这是它成为人工智能与数据分析领域强者的关键。有很多Python开发人员想知道常用的Python库有哪些&#xff0c;接下来就给大家详细介绍一下。ArrowPython中处理时间的库…

三次握手面试题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 for嵌套循环_PHP中的for循环怎样嵌套

本篇文章主要介绍 PHP中的for循环怎样嵌套&#xff0c;感兴趣的朋友参考下&#xff0c;希望对大家有所帮助。for循环的执行原理&#xff1a;for循环的参数有(初始值&#xff1b;判断条件&#xff1b;更新循环变量表达式) 三者均不是必须的&#xff0c;若三者不完整则必须在适当…

Visio显示不完整

下面显示不完整的话&#xff0c;选中对象&#xff0c;菜单栏设置&#xff08;点击对象&#xff0c;右键并没有段落选项&#xff09;行距为单倍&#xff1b;右侧显示不完整&#xff0c;选中后右键设置环绕方式为负于文字上方&#xff0c;原来是嵌入型。

python2 python3 通信_python与USB通信

Date周三 04 十一月 2015TagsUSB/PythonPyUSB依赖于一些USB的驱动程序, 这个貌似叫做无驱驱动, 其中libusb是一统天下者, 当然就要用这个咯. 那么问题来了, libusb这个驱动是怎么装到要开发的设备上呢? 在windows下答案是Zadig, 这个和rtlsdr用的方案是一致的.下载了最新的Zad…

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…

python学完面向对象之后_Python学完基础语法后,再往后应该学什么?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼第一阶段&#xff1a;Python语言及应用课程内容&#xff1a;Python语言基础&#xff0c;面向对象设计&#xff0c;多线程编程&#xff0c;数据库交互技术&#xff0c;前端特效&#xff0c;Web框架&#xff0c;爬虫框架&#xff0c;…

百度应用部署秘籍

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

php新闻删除功能设计,php原生开发新闻站之删除新闻

我们前两篇文章都完成了新闻的添加、修改。那么我们这个节课程就给大家介绍删除新闻&#xff0c;这个比之前的两个都要简单点&#xff01;首先创建一个new_delete.php,接着我们要在新闻列表页找到删除的按钮&#xff0c;给这个按钮加一个连接&#xff0c;我们同样需要通过id来传…

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

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