当前位置: 首页 > news >正文

Java容器使用注意点

前置:问题

  1. 判空
  2. 集合转map
  3. 集合遍历
  4. 集合去重
  5. 集合转数组
  6. 数组转集合

一:集合判空

《阿里巴巴 Java 开发手册》的描述如下:

判断所有集合内部的元素是否为空,使用 isEmpty() 方法,而不是 size()==0 的方式。
我们在开发中也常用Spring提供的CollectionUtil.isEmpty(list)

// ConcurrentHashMap 的 size() 方法和 isEmpty() 方法的源码。
public int size() {long n = sumCount();return ((n < 0L) ? 0 :(n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :(int)n);
}
final long sumCount() {CounterCell[] as = counterCells; CounterCell a;long sum = baseCount;if (as != null) {for (int i = 0; i < as.length; ++i) {if ((a = as[i]) != null)sum += a.value;}}return sum;
}
public boolean isEmpty() {return sumCount() <= 0L; // ignore transient negative values
}

Spring中的源码

// 判null+判内容
public static boolean isEmpty(@Nullable Collection<?> collection) {return (collection == null || collection.isEmpty());}

Spring底层是直接使用isEmpty进行判空的。

这是因为 isEmpty() 方法的可读性更好,并且时间复杂度为 O(1)。

绝大部分我们使用的集合的 size() 方法的时间复杂度也是 O(1),不过,也有很多复杂度不是 O(1) 的,比如 java.util.concurrent 包下的某些集合(ConcurrentLinkedQueue\ConcurrentHashMap…)出于时间复杂度的考虑


二:集合转Map

《阿里巴巴 Java 开发手册》的描述如下:

在使用 java.util.stream.Collectors 类的 toMap() 方法转为 Map 集合时,一定要注意当 value 为 null 时会抛 NPE 异常。

class Dog {private String id;private String sex;
}List<Dog> list = new ArrayList<>();
list.add(new Dog("1212121","公"));
// value为null值,会报npe
list.add(new Dog("435",null));
// 空指针异常
list.stream().collect(Collectors.toMap(Dog::getId, Dog::getSex));

异常原因

  • value判空
    在这里插入图片描述

集合遍历

《阿里巴巴 Java 开发手册》的描述如下:

不要在 foreach 循环里进行元素的 remove/add 操作(这个问题我踩过坑,和你想删的东西绝对不一样)。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。

通过反编译你会发现 foreach 语法底层其实还是依赖 Iterator 。不过, remove/add 操作直接调用的是集合自己的方法,而不是 Iterator 的 remove/add方法

这就导致 Iterator 莫名其妙地发现自己有元素被 remove/add ,然后,它就会抛出一个 ConcurrentModificationException 来提示用户发生了并发修改异常。这就是单线程状态下产生的 fail-fast 机制。

Java8之后使用removeIf

List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; ++i) {list.add(i);
}
// 这个蛮好用的
list.removeIf(filter -> filter % 2 == 0); /* 删除list中的所有偶数 */
System.out.println(list); /* [1, 3, 5, 7, 9] */

集合去重

《阿里巴巴 Java 开发手册》的描述如下:

可以利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains() 进行遍历去重或者判断包含操作。

// Set 去重代码示例// 无hash冲突时时间复杂度O(1)
public static <T> Set<T> removeDuplicateBySet(List<T> data) {if (CollectionUtils.isEmpty(data)) {return new HashSet<>();}return new HashSet<>(data);
}// List 去重代码示例//时间复杂度O(n) ,跟进去看contains方法就可以看出来
public static <T> List<T> removeDuplicateByList(List<T> data) {if (CollectionUtils.isEmpty(data)) {return new ArrayList<>();}List<T> result = new ArrayList<>(data.size());for (T current : data) {if (!result.contains(current)) {result.add(current);}}return result;
}// testMyList<Integer> integers = Arrays.asList(1, 1, 1, 12, 32, 32, 3245, 3123, 6, 6);// 推荐去重方式HashSet<Integer> integers1 = new HashSet<>(integers);System.out.println(JSON.toJSONString(integers1));

集合转数组

《阿里巴巴 Java 开发手册》的描述如下:

使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。

toArray(T[] array) 方法的参数是一个泛型数组,如果 toArray 方法中没有传递任何参数的话返回的是 Object类 型数组。

String [] s= new String[]{"dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A"
};
List<String> list = Arrays.asList(s);
Collections.reverse(list);
//没有指定类型的话会报错
s=list.toArray(new String[0]);

由于 JVM 优化,new String[0]作为Collection.toArray()方法的参数现在使用更好,new String[0]就是起一个模板的作用,指定了返回数组的类型,0 是为了节省空间,因为它只是为了说明返回的类型。详见:https://shipilev.net/blog/2016/arrays-wisdom-ancients/


数组转集合

《阿里巴巴 Java 开发手册》的描述如下:

使用工具类 Arrays.asList() 把数组转换成集合时,不能使用其修改集合相关的方法, 它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

Arrays.asList()在平时开发中还是比较常见的,我们可以使用它将一个数组转换为一个 List 集合。

String[] myArray = {"Apple", "Banana", "Orange"};
List<String> myList = Arrays.asList(myArray);
//上面两个语句等价于下面一条语句
List<String> myList = Arrays.asList("Apple","Banana", "Orange");

JDK源码

/***返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁,* 与 Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。*/
public static <T> List<T> asList(T... a) {return new ArrayList<>(a);
}

相关文章:

Java容器使用注意点

前置&#xff1a;问题 判空集合转map集合遍历集合去重集合转数组数组转集合 一&#xff1a;集合判空 《阿里巴巴 Java 开发手册》的描述如下&#xff1a; 判断所有集合内部的元素是否为空&#xff0c;使用 isEmpty() 方法&#xff0c;而不是 size()0 的方式。 我们在开发中也…...

密文题解(图论+字典树)

题目大意 有一段长度为nnn的密文&#xff0c;密文的每一位都可以用一个非负整数来描述&#xff0c;并且每一位都有一个权值aia_iai​。你可以操作任意多次&#xff0c;每次操作可以选择任意一段密文&#xff0c;花费选择的所有位上权值的异或和的代价获得这段密文每一位的异或…...

Baumer工业相机堡盟工业相机如何通过BGAPISDK里的工具函数来计算工业相机的实时帧率(C#)

Baumer工业相机堡盟工业相机如何通过BGAPISDK里函数来计算相机的实时帧率&#xff08;C#&#xff09;Baumer工业相机Baumer工业相机的帧率的技术背景Baumer工业相机的帧率计算方式在BufferEvent声明显示FrameID设计显示帧率的函数Baumer工业相机通过BGAPI SDK计算帧率的优势​B…...

数据结构与常量(Java)

目录 1.字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 补充&#xff1a;变量 int long short double和float char boolean byte 4.类型转换 类型提升小结 5. 字符串类型 1. int 转成 String 2. String 转成 int 1.字面常量 类似System.Out.p…...

【LeetCode】剑指 Offer 54. 二叉搜索树的第k大节点 p269 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/ 1. 题目介绍&#xff08; 54. 二叉搜索树的第k大节点&#xff09; 给定一棵二叉搜索树&#xff0c;请找出其中第 k 大的节点的值。 【测试用例】&#xff1a; 示例 1: 示例2&…...

[工具类] post请求 获取request对象, 获取request的请求体(body)参数

目录 引言: 1. 获取request对象的几种常用方式 -> 1.1 获取请求对象 通过请求上下文对象 获取信息[推荐] -> 1.2 在controller层直接获取[不推荐 侵害性太强] -> 1.3 interceptor中获取[部分业务中使用] -> 1.4 request常用api简介 2. 获取request的body的工具…...

Golang 多版本安装小工具G

​ voidint制作的Golang版本安装管理&#xff0c;非常好用。想装就装&#xff0c;想换版本就换版本 除了一些使用go install的场景可能有不兼容&#xff0c;主要是安装了工具有时候不能直接用。 GitHub - voidint/g: Golang Version Manager​​​​​​​ 使用方式很简单&a…...

day29—选择题

文章目录1.HashSet子类依靠什么方法区分重复元素&#xff08;C&#xff09;2.以下代码在编译和运行过程中会出现什么情况&#xff08;A&#xff09;3.有这么一段程序&#xff0c;执行的结果是&#xff08;C&#xff09;1.HashSet子类依靠什么方法区分重复元素&#xff08;C&…...

day8 互斥锁/读写锁的概念及使用、死锁的避免

目录 互斥锁的概念和使用 线程通信 - 互斥 互斥锁的创建和销毁 互斥锁的创建 互斥锁的销毁 互斥锁的使用 申请锁 释放锁 互斥锁的概念和使用 线程通信 - 互斥 临界资源&#xff1a; 一次只允许一个任务&#xff08;进程、线程&#xff09;访问的共享资源&#xff1b…...

2023-04-13 monetdb-str类型变长存储-分析

摘要: monetdb的列的基本抽象是BAT,但是对于列数据的存储方式, 对于固定长度和不固定长度,使用了不同的存储方式。 固定长度的数据比如int,int64之类的, 直接存储在了数据tail文件。 但是对于不固定长度比如string, 则使用另外一个独立的theap文件存储, tail文件仅保留对于…...

011:Mapbox GL两种方式隐藏logo和版权,个性化版权的声明

第011个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中用两种方式隐藏logo和版权,并个性化版权的声明 。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共91行)相关API参考:专栏目标示例效果 配置方式…...

结合PCA降维的DBSCAN聚类方法(附Python代码)

目录 前言介绍&#xff1a; 1、PCA降维&#xff1a; &#xff08;1&#xff09;概念解释&#xff1a; &#xff08;2&#xff09;实现步骤&#xff1a; &#xff08;3&#xff09;优劣相关&#xff1a; 2、DBSCAN聚类&#xff1a; &#xff08;1&#xff09;概念解释&a…...

限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)

限流 限流是面试中的常见的面试题&#xff08;尤其是大厂面试、高P面试&#xff09; 注&#xff1a;本文以 PDF 持续更新&#xff0c;最新尼恩 架构笔记、面试题 的PDF文件&#xff0c;请到文末《技术自由圈》公号获取 为什么要限流 简单来说&#xff1a; 限流在很多场景中用来…...

Redis用于全局ID生成器、分布式锁的解决方案

全局ID生成器 每个店铺都可以发布优惠卷 当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增id就存在一些问题&#xff1a; 1.id的规律性太明显 2.受单表数据量的限制 全局ID生成器&#xff0c;是一种在分布式系…...

OpenTex 企业内容管理平台

OpenText 企业内容管理平台 将内容服务与领先应用程序集成&#xff0c;弥合内容孤岛、加快信息流并扩大治理 什么是内容服务集成&#xff1f; 内容服务集成通过将内容管理平台与处于流程核心的独立应用程序和系统连接起来&#xff0c;支持并扩展了 ECM 的传统优势。 最好的内…...

【0基础学爬虫】爬虫基础之数据存储

大数据时代&#xff0c;各行各业对数据采集的需求日益增多&#xff0c;网络爬虫的运用也更为广泛&#xff0c;越来越多的人开始学习网络爬虫这项技术&#xff0c;K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章&#xff0c;为实现从易到难全方位覆盖&#xff0c;特设【0基础学…...

Redis与本地缓存组合使用(IT枫斗者)

Redis与本地缓存组合使用 前言 我们开发中经常用到Redis作为缓存&#xff0c;将高频数据放在Redis中能够提高业务性能&#xff0c;降低MySQL等关系型数据库压力&#xff0c;甚至一些系统使用Redis进行数据持久化&#xff0c;Redis松散的文档结构非常适合业务系统开发&#xf…...

手把手教你学习IEC104协议和编程实现 十 故障事件与复位进程

故障事件 目的 在IEC104普遍应用之前,据我了解多个协议,再综合自动化协议中,有这么一个概念叫“事故追忆”,意思是当变电站出现事故的时候,不但要记录事故的时间,还需记录事故前后模拟量的数据,从而能从一定程度上分析事故产生的原因,这个模拟量就是和今天讲解的故障…...

浅析分布式理论的CAP

大家好&#xff0c;我是易安&#xff01; 今天让我们来聚焦于分布式系统架构中的重要理论——CAP理论。在分布式系统中&#xff0c;可用性和数据一致性是两个至关重要的因素&#xff0c;而CAP理论就是在这两者之间提供了一种权衡的原则&#xff0c;帮助我们在设计分布式系统时进…...

使用 TensorFlow 构建机器学习项目:6~10

原文&#xff1a;Building Machine Learning Projects with TensorFlow 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#x…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...