不好意思,list.contain 去重该换换了!

2023-11-05

c02249ba932b3965b294542f40e49d6e.jpeg

程序员的成长之路

互联网/程序员/技术/资料共享 

关注

阅读本文大概需要 3.5 分钟。

来自:blog.csdn.net/qq_35387940/article/details/129885310

最近又是一轮代码review , 发现了一些实现去重的代码,在使用 list.contain ......

6e4c1d90cf9893c3c20c2c6378b73712.png

我沉思,是不是其实很多初学者也存在这种去重使用问题?

所以我选择把这个事情整出来,分享一下。

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

首先是造出一个 List模拟数据,一共2W条,里面有一半数据1W条是重复的:

public static List<String> getTestList() {
    List<String> list = new ArrayList<>();
    for (int i = 1; i <= 10000; i++) {
        list.add(String.valueOf(i));
    }
    for (int i = 10000; i >= 1; i--) {
        list.add(String.valueOf(i));
    }
    return list;
}

先看看我们用 contain 去重的代码:

/**
 * 使用 list.contain 去重
 *
 * @param testList
 */
private static void useContain2Distinct(List<String> testList) {
    System.out.println("contains 开始去重,条数:" + testList.size());
    List<String> testListDistinctResult = new ArrayList<>();
    for (String str : testList) {
        if (!testListDistinctResult.contains(str)) {
            testListDistinctResult.add(str);
        }
    }
    System.out.println("contains 去重完毕,条数:" + testListDistinctResult.size());
}

我们调用一下看看耗时:

public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    useContainDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

耗时:

dbb0415e49afe0ca23afa91744d73e08.png

评价:list.contain 的效率,我的建议是,知道就行,别用。

众所周知 Set 不存在重复数据, 所以我们来看看使用 HashSet 去重的性能:

ps:这里是采取使用 set 的 add 方法做去重

/**
 * 使用set去重
 *
 * @param testList
 */
private static void useSetDistinct(List<String> testList) {
    System.out.println("HashSet.add 开始去重,条数:" + testList.size());
    List<String> testListDistinctResult = new ArrayList<>(new HashSet(testList));
    System.out.println("HashSet.add 去重完毕,条数:" + testListDistinctResult.size());
}

我们调用一下看看耗时:

public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    useSetDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

耗时:

986699b57e66974f0331136327bfc37a.png

评价:HashSet 的效率,我的建议是推荐。

为什么耗时差距这么大?

不多说,我们看源码:

list.contains(o):

2d7010079906e6b85a2b5dc255b6b239.png

可以看到里面用到了 index(o) :

697153fb751f697bf3309bc0a291d0a6.png

时间复杂度 :O(n) n: 元素个数

那么我们看看 set.add(o) 是怎么样的 :

491830b6e292b0547dd847460c7be421.png

map的add , 老生常谈就不谈了,hash完 直接塞到某个位置, 时间复杂度 :O(1)  。

所以 O(n) 和 O(1) 谁快谁慢?显然。

2c810d8ec45a7486f40dc7162849dadc.png

时间复杂度也是:O(1)

17604913bd7cb03efd83c75dec05918f.png

那么我们最后再看看别的去重:

双for循环 ,remove去重

/**
 * 使用双for循环去重
 * @param testList
 */
private static void use2ForDistinct(List<String> testList) {
    System.out.println("list 双循环 开始去重,条数:" + testList.size());
    for (int i = 0; i < testList.size(); i++) {
        for (int j = i + 1; j < testList.size(); j++) {
            if (testList.get(i).equals(testList.get(j))) {
                testList.remove(j);
            }
        }
    }
    System.out.println("list 双循环  去重完毕,条数:" + testList.size());
}
public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    use2ForDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

耗时:

94ce8f2942c0f1a088668d7c9865aeb0.png

评价:知道就行,图个乐,别用,贼慢,而且代码看起来乱

stream的distinct去重:

/**
 * 使用Stream 去重
 *
 * @param testList
 */
private static void useStreamDistinct(List<String> testList) {
    System.out.println("stream 开始去重,条数:" + testList.size());
    List<String> testListDistinctResult = testList.stream().distinct().collect(Collectors.toList());
    System.out.println("stream 去重完毕,条数:" + testListDistinctResult.size());
}
public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    useStreamDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

耗时:

d5f1fead4c4fa38b2f1dc11a5bc0d9e0.png

评价:还不错,主要是代码也蛮简洁,有一点点动心。

<END>

推荐阅读:

再见!微软官宣放弃Mac 版 Visual Studio IDE

字节一面:post为什么会发送两次请求?

互联网初中高级大厂面试题(9个G)
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper......等技术栈!
⬇戳阅读原文领取!                                 朕已阅
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

不好意思,list.contain 去重该换换了! 的相关文章

随机推荐

  • 机器学习与深度学习入门环境安装

    机器学习与深度学习入门环境安装 1 编程语言 2 开发平台 3 机器学习工具包 4 深度学习框架 1 编程语言 Python 胶水语言 集成度高 简单实用 受众面广 开发者社区和资源丰富 功能强大 十分适合新手入门与科研工作者使用 但运行速
  • C++如何判断变量类型

    C 如何判断变量类型 使用 typeid 判断其类型 需要在编译语言选项中选择 RTTI 编译选项 例子 引用自这里 详情可以看这里 include
  • SyntaxError: Unexpected token o in JSON at position 1

    用JSON parse value 将string对象转换成object对象出错 报错原因 重复转换 由value本身就是object对象引发的 因为value本身就是object对象 此时再使用JSON parse value 方法后返回
  • 亚马逊+纽约大学开源图神经网络框架DGL

    最近 纽约大学 纽约大学上海分校 AWS上海研究院以及AWS MXNet Science Team共同开源了一个面向图神经网络及图机器学习的全新框架 命名为Deep Graph Library DGL 据介绍 这个框架在测试时表现出了良好的
  • cenetOS 系统开机启动服务脚本

    在centos7中增加脚本有两种常用的方法 以脚本autostart sh为例 bin bash description 开机自启脚本 usr local tomcat bin startup sh 启动tomcat 方法一 1 赋予脚本可
  • 去掉xcode源码末尾的空格【转载的这篇还没有具体操作过,希望对大家有用】

    去掉xcode源码末尾的空格 Dec 10th 2011 在用xcode开发的时候 很容易就在行末增加一些空格了 这些空格在上传到review board上后 就会被特别的颜色显示出来 因为一种好的编程风格是说 不应该在行末增加不必要的空格
  • 关于在macOS 12 Monterey上驱动Intel网卡、蓝牙

    前言 相信自从macOS12发布以后 不少黑苹果用户都已经升级 在这一部分用户中又有不少用户使用的是Intel网卡 而升级macOS12后 Intel网卡 蓝牙并不能正常驱动 前一段时间由于电脑问题 其中有3个月我没有使用黑苹果 在前不久
  • 使用JVisualVM远程监控Tomcat

    用JVisualVM连接远程JVM 监控系统运行性能参数 作用 JVM和监控的应用程序运行在不同的服务器上 减轻应用程序的负担 特别是HeapDupm的时候 应用常能够续负担很大 1 为 10 87 40 141 上的 tomcat 配置
  • 网络协议和Netty

    文章标题 网络协议 计算机网络体系结构 OSI 七层模型 TCP IP 模型 TCP IP 协议族 TCP 和 UDP 地址和端口号 端口号的确定 端口号与协议 TCP IP TCP 三次握手 TCP 的三次握手的漏洞 TCP 四次挥手 分
  • 建议办公室的空调上都贴上“最环保健康温度26度”

    建议办公室的空调上都贴上 最环保健康温度26度 早上来到办公室看到办公室的空调上贴着 最环保健康温度26度 公司可以省下一小笔 大家可以健康的环境下工作 看到自已的建议被采纳了 心里美啊 愿有更多的空调能贴上 最环保健康温度26度 转贴 为
  • STM32-cubemx-DMA-UART-笔记(振兴中华)

    原文章 STM32 HAL库 STM32CubeMX教程十一 DMA 串口DMA发送接收 Z小旋的博客 CSDN博客 hal dma include
  • Java—面向对象——类与对象

    目录 一 现有技术解决问题 二 类与对象的关系示意图 三 类和对象的关系与区别 四 对象在内存中的存在形式 五 属性 成员变量 字段 六 如何创建对象 七 如何访问属性 一 现有技术解决问题 单独的定义变量解决 缺点 不利于数据的管理 使用
  • PyCharm连接Docker中的容器(ubuntu)

    一 为什么要用Pycharm链接Docker中的ubuntu 因为在进行深度学习的时候 基于windows系统在开发的过程中 老是出现很多问题 大多数是环境问题 尽管安装了Conda 也不能很好的解决问题 使用ubuntu是最好的选择 二
  • tar命令如何解压指定文件到指定目录下

    举一个例子 解压 a tar gz 包里文件名以 one 开头的文件到 tmp 文件夹下 tar xzv C tmp f a tar gz one
  • FBXSDK2018 plugin for Unity

    1 下载FBXSDK 点击打开链接 2 安装SDK 记住你所安装的目录 3 visualstudio 新建 C 空项目 首先配置 C C 附加包含目录 你安装sdk 路径下的include 4 设置预处理器 假设是Debug x64 WIN
  • 原地逆转链表的多种方案

    原地逆转链表的多种方案 include
  • 正大期货:期货交易规则和操作方法?

    1 实行t 0的交易方式 即投资者当天买入的期货 在当天就能卖出 2 双向交易 即投资者可以进行做多操作 也可以进行做空交易 3 保证金制度 即投资者交易期货需要交纳一定比例的保证金 4 强制平仓制度 即当投资者的保证金不足时 期货公司为了
  • java获取微信用户信息(UnionID)

    本篇主要是针对用户关注公众号 然后利用接口获取用户的信息包括unionid信息 首先就是获取微信access token的值 官方文档 https mp weixin qq com wiki t resource res main id m
  • rockchip rk3368(px5)车载开发之路2,屏幕正常显示(不对的地方是UI)

    本系列记载作者来到一个新的车载后装市场小公司 负责从新开始维护一套代码的心路过程 系统使用瑞芯微的rk3368芯片 版本是PX5 Android 8 0 release 20180726 从无到有的每个patch修改以及思考 其中着重点是驱
  • 不好意思,list.contain 去重该换换了!

    程序员的成长之路 互联网 程序员 技术 资料共享 关注 阅读本文大概需要 3 5 分钟 来自 blog csdn net qq 35387940 article details 129885310 最近又是一轮代码review 发现了一些实