一般使用List集合,估计都是使用这个ArrayList,一般呢也就是简单遍历数据和存储数据。
很少使用到add(int index, E element)和set(int index, E element)两个方法。这两个方法,乍一看,就是在指定的位置插入一条数据。
区别:
- set()是更新,更新指定下标位置的值。
- add()是添加,区别于一般的add(E e),这个就是有个位置的概念,特殊位置之后的数据,依次往后移动就是了。
看下面代码:
public class ArrayListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>(2);
System.out.println("list大小为:" + list.size());
list.add("12");
System.out.println("list大小为:" + list.size());
list.set(1,"sss");
list.add(1,"放在下标为1的位置");
list.add("22");
System.out.println("list大小为:" + list.size());
System.out.println(list.toString());
list.add(1,"放在下标为1的位置");
System.out.println("list大小为:" + list.size());
System.out.println(list.toString());
}
}
回答上面的问题?和下面的输出结果对比一下,内容分析见后:

估计,很多人都大出所料吧。结果怎么是这样呢!下面有这么几个坑。
解释:
1,List<String> list = new ArrayList<>(2)
这个乍一看,还以为像数组一样,你初始化了个长度为2的数组,然后你就可以随意修改下标为0,1的内容。当然0,1是肯定不会下标越界的。我当时也是这么想的。然而不是的。
源码里面的构造函数的注释说明:这个真的是在底层新建了个长度为2的数组Object[],但是他又不是我们经常看到的一般数组。这个是空的。当前list集合仍然是一个带有初始容量的empty list。
2,list.size()
我上来也是想当然的以为,这个size()不就是上面的那个2吗!但是我错了。
源码中ArrayList的size属性对应的注释是:The size of the ArrayList (the number of elements it contains).
这个size是表示这个集合包含的元素的个数,而不是底层数组的大小。
3,list.set(1,"sss")
在知道了上面的2个坑之后,这个就好解释了。代码是要设置下标为1的值,但是。在源码中有 rangeCheck(index);
1 2 3 4 |
|
这个时候,index设置的index是1,但是ArrayList的大小size是1,也就是当前List只有一个值为12,index=0元素。so,就异常啦。
4,list.add(1,"放在下标为1的位置")
这个和上面相似,但还是有点不一样,上面判断是大于等于size,但是在这个add方法,却是要大于才可以。
而且还有个专门的check方法for add,如下:rangeCheckForAdd(index);
1 2 3 4 |
|
那这个在下标为1的位置添加元素,判断 1 > 1 不成立,那么就可以顺利添加了。这个就不异常啦。
但是,你要是在数组声明完,直接在下标为1的位置,这么干,就异常了。就不在继续分析了。
5,还有个问题,就是你在一个位置一直add(index ,element)
这个不仅仅是把index位置的数据给替换啦,而且把之前这个位置的数据给依次向后移动啦,这个跟map的结构不一样,map是更新指定位置的数据,其他的数据不动,这个list竟然是把把数据平移啦。
ArrayList的常用基础总结:
1.导入
1 |
|
2.定义数组list
ArrayList<类名> list = new ArrayList<类名>(); 不能是基本类型,必须是类
3.获取集合大小的方法:
size();
4.存入数据的方法:
add(Object object);从下标0开始加入
add(int idx,Object object);将object插入索引为idx的位置,idx<=list.size();
存进不同的对象要单个new,不能通过改变值后加入数组。(涉及到内存)
5.删除
remove(int idx);删除索引为idx的元素,返回该元素,可以用变量去接收,也可不接收
6.清空
clear(); 清空数组
7.替换
set(int idx,Object object); 把object元素和原本索引为idx的元素替换
8.获取指定位置元素
Object get(int idx);
9.判空
bool isEmpty(); 一般不用,size()可以用于判空
10.判断是否有某元素
bool contains(Object object); 基本不用,可以通过查找元素的索引来解决
11.查找元素的索引
int indexOf(Object object); 如果元素存在,则返回索引,否则返回-1,通过是不是-1判断元素在不在数组里
12..对数组list排序
导入Collections类;
1 |
|
(1)默认自然排序,从小到大
Collections.sort(list); //不可以new出Collections的对象,直接用
(2)自定义排序
导入Comparator类;
1 |
|
创建对象的时候需要实现抽象方法compare(),实现自定义排序
package my_acm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;//自定义排序
//import java.lang.Integer;//lang包中的类不用导也能直接用
public class MyTest4 {
public static void main(String [] args) {
ArrayList<Point> list1 = new ArrayList<Point>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
//ArrayList<int> list3 = new ArrayList<int>();//报错,基本数据类型不能
Comparator<Point> comparator = new Comparator<Point>() {
public int compare(Point p1, Point p2) {
if(p1.id!=p2.id)
return p1.id-p2.id;
else
{
if(p1.age!=p2.age)
return p1.age-p2.age;
else
return 0;//不像C++,这里的if-else需要匹配
}
}
};
Point p1 = new Point();
p1.id=11;p1.age=21;
list1.add(p1);
Point p2 = new Point();
p2.id=9;p2.age=44;
list1.add(p2);
Point p3 = new Point();
p3.id=2;p3.age=68;
list1.add(p3);
/** 修改变量的值在加到数组里是不可行的,(
p3.id=14;p3.age=23;
list1.add(p3);
*/
for(int i=0;i<list1.size();i++) {
System.out.println( "i="+i+" id="+list1.get(i).id+" age="+list1.get(i).age);
}
Collections.sort(list1,comparator);
System.out.println("按id排序后");
for(int i=0;i<list1.size();i++) {
Point x = new Point();
x=list1.get(i);
System.out.println( "i="+i+" id="+x.id+" age="+x.age );
}
}
}
class Point{
int id;
int age;
}
输出结果:
1 2 3 |
|
按id排序后
1 2 3 |
|
来源:CSDN
作者:Frank.King
链接:https://blog.csdn.net/luqingshuai_eloong/article/details/104471558