一、把数组转成ArrayList

List<String> list = Arrays.asList(arr);

//以下带伪代码来自Arrays类中
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
}

使用Arrays.asList()方法可以得到一个ArrayList,但是得到这个ArrayList其实是定义在Arrays类中的一个私有的静态内部类。这个类虽然和java.util.ArrayList同名,但是并不是同一个类。java.util.Arrays.ArrayList类中实现了set()get()contains()等方法,但是并没有定义向其中增加元素的方法。也就是说通过Arrays.asList()得到的ArrayList的大小是固定的。

二、在循环中删除列表中的元素

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(int i=0;i<list.size();i++){
list.remove(i);
}
System.out.println(list);

输出结果:

[b,d]

以上代码的目的是想遍历删除list中所有元素,但是结果却没有成功。原因是忽略了一个关键的问题:当一个元素被删除时,列表的大小缩小并且下标也会随之变化,所以当你想要在一个循环中用下标删除多个元素的时候,它并不会正常的生效。

也有些人知道以上代码的问题就由于数组下标变换引起的。所以,他们想到使用增强for循环的形式:

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(String s:list){
if(s.equals("a")){
list.remove(s);
}
}

但是,很不幸的是,以上代码会抛出ConcurrentModificationException,有趣的是,如果在remove操作后增加一个break,代码就不会报错:

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(String s:list){
if(s.equals("a")){
list.remove(s);
break;
}
}

迭代器被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 迭代器会马上抛出java.util.ConcurrentModificationException 异常。

所以,正确的在遍历过程中删除元素的方法应该是使用Iterator:

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String s = iter.next(); if (s.equals("a")) {
iter.remove();
}
}

next()方法必须在调用remove()方法之前调用。如果在循环过程中先调用remove(),再调用next(),就会导致异常ConcurrentModificationException。原因如上。

三、迷之求和

public void test_add(){
int num = 0;
for (int i = 0; i < 100; i++) {
num = num++;
}
System.out.println(num);
}

最终 num 结果为 0,num++ 根本没起啥作用。因为后++,是先用结果,在++操作,不会给赋值。正确写法是:num = ++ num;

四、无用日志

public boolean ruleEngine(MatterReq req) {
try {
// 业务流程
} catch (Exception e) {
logger.error(e); // 只打异常,不打入参信息
}
}

五、耗时遍历

public void test_LinkedList() {
// 初始化100万数据
List<Integer> list = new LinkedList<Integer>(1000000); // 遍历求和
int sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
} }

乍一看可能觉得没什么问题,但是这个遍历求和会非常慢。主要因为链表的数据结构,每一次list.get(i)都是从链表的头开始查找,与ArrayList不同,LinkedList它时间复杂度是O(n)。那如果说你不知道对方传过来的是LinkedList还是ArrayList呢,其实可以通过list instanceof RandomAccess 进行判断。ArrayList 有随机访问的实现,LinkedList 是没有。同时也可以使用增强的for循环或者Iterator进行遍历。

Java开发人员最容易出现的几类错误的更多相关文章

  1. Java开发人员最常犯的10个错误

    这个列表总结了10个Java开发人员最常犯的错误. Array转ArrayList 当需要把Array转成ArrayList的时候,开发人员经常这样做: List<String> list ...

  2. 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序

    面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序 Ajax 为更好的 Web 应用程序铺平了道路 在 Web 应用程序开发中,页面重载循环是最大的一个使用障碍,对于 Java™ ...

  3. Java开发人员必须掌握的Linux命令-学以致用(5)

    ================================================= 人工智能教程.零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助! 点击查看高清无码教程 == ...

  4. Java开发人员必须掌握的两个Linux魔法工具(四)

    子曰:"工欲善其事,必先利其器." 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣) ...

  5. Java开发人员必须掌握的Linux命令(三)

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣)的表达来讲解知识或者技术,让学习之旅充满乐趣,这就是写博 ...

  6. Java开发人员必须掌握的Linux命令(二)

    子曰:"工欲善其事,必先利其器." 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣)的表达来讲解让知识或者技术,让学习之旅充满乐趣,这就是写博文的初心. 本篇的旅 ...

  7. Spring Boot 针对 Java 开发人员的安装指南

    Spring Boot 可以使用经典的开发工具或者使用安装的命令行工具.不管使用何种方式,你都需要确定你的 Java 版本为 Java SDK v1.8 或者更高的版本.在你开始安装之前,你需要确定你 ...

  8. JAVA开发人员画图表总结(ECHARTS)

    随着大数据的到来,越来越多的数据需求需要开发,而这些需求不可避免需要使用JS画出图表,而大多后端JAVA开发人员对JS不太熟悉,导致身心倍受折磨,今天记录以下最近我使用echarts的步骤,供参考: ...

  9. 【运维】Java开发人员掌握的Linux命令

    作为Java开发人员,要掌握常用的Linux命令. 为什么要写此文,笔者的Linux很厉害?NoNoNo,正因为笔者不熟悉Linux才写此文,以作整理. 最主要的命令 查询命令的简要用法,help 当 ...

随机推荐

  1. PTA 求二叉树的深度

    6-7 求二叉树的深度 (6 分)   本题要求实现一个函数,可返回二叉树的深度. 函数接口定义: int Depth(BiTree T); T是二叉树树根指针,函数Depth返回二叉树的深度,若树为 ...

  2. python3 虚拟环境 venv

    创建一个虚拟环境: python -m venv test            (test 为创建的虚拟环境目录) 激活虚拟环境: test\Scripts\activate            ...

  3. springboot源码解析-管中窥豹系列之bean如何生成?(十四)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  4. JVM虚拟机知识问答总结(简单复习,快速回忆!)

    写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...

  5. 【linux】驱动-4-LED芯片手册分析

    目录 前言 4. LED芯片手册分析 4.1 内存管理单元MMU 4.1.1 MMU的功能 4.1.2 TLB的作用 4.2 地址转换函数 4.2.1 ioremap函数 4.2.2 iounmap函 ...

  6. linux程序开机自动启动

    linux如果需要实现开机启动, 可以找到 $HOME/.config/autostart 目录(没有的话新建一个),在该文件夹下创建一个空文件,文件名自拟,后缀必须是desktop,如:dingda ...

  7. Dynamics CRM证书更换

    Dynamics CRM产品一般有两种认证方式.第一种是基于声明的内部访问也就是无证书单纯用账号密码验证.第二种就是联合身份认证,需要安装网站证书. 对于联合身份认证的情况因为需要安装证书,而且证书是 ...

  8. 一文简述JAVA内部类和异常

    内部类和异常 内部类 在一个类的内部定义的一个类,例如,A类中定义了一个B类,则B类相对于A类就是内部类,而A类相对于B类就是外部类 成员内部类 静态内部类 局部内部类 匿名内部类 成员内部类 pub ...

  9. 一次死锁导致CPU异常飘高的整个故障排查过程

    目录 一.问题详情 top 命令截图 联系腾讯云排查 检查系统日志发现异常 二. 问题解析 三.问题原因 最终结论 四.扩展 进程的几种状态 马后炮 如何快速清理僵尸进程(Z) 内核参数相关 如何查看 ...

  10. ECMAScript 2019(ES10)新特性简介

    简介 ES10是ECMA协会在2019年6月发行的一个版本,因为是ECMAScript的第十个版本,所以也称为ES10. 今天我们讲解一下ES10的新特性. ES10引入了2大特性和4个小的特性,我们 ...