文章目录
1. 前言
Java集合类是一种特别有用的工具类,可以用于存储数量不等的对象,并可以实现常用的数据结构,如栈,队列等。Java集合大致可分为Set,List,Queue和Map四种体系。
Java集合类主要有两个接口派生而出:Collection和Map, Collection和Map是Java集合框架的根接口,这两个接口又包含一些子接口或实现类。如图是Collection接口、子接口及其实现类的继承树。
2. Collection接口
Collection定义的集合操作(如图),我们使用的其子接口ArrayList可用的API也是一样的。
ArrayList继承树
3. ArrayList基本操作
ArrayList是Collection的子接口,其实现了Collection接口所有功能,因ArrayList是基于数组实现的集合类,因此其也增加了一些其他一些特殊接口
3.1.1 添加元素
public static void arrayListAddTest() {
//按元素添加
ArrayList c = new ArrayList();
c.add("孙悟空");
c.add(6);
System.out.println("c的集合个数为:" + c.size());
System.out.println("c的集合内容:");
Iterator iterator = c.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//使用集合添加
ArrayList c2 = new ArrayList();
c2.add("猪八戒");
c2.add(200);
c.addAll(c2);
System.out.println("c的集合个数为:" + c.size());
System.out.println("c的集合内容:");
Iterator it2 = c.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
}
3.1.2 删除元素
public static void arrayListRemoveTest() {
System.out.println("ArrayList add test:");
ArrayList c1 = new ArrayList();
c1.add("孙悟空");
c1.add(100);
c1.add("猪八戒");
c1.add(50);
System.out.println("c1集合元素:");
Iterator it1 = c1.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
c1.remove("猪八戒"); //删除一次元素
Iterator it2 = c1.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
ArrayList c2 = new ArrayList(); //集合c2: 孙悟空,100
c2.add("孙悟空");
c2.add(100);
c1.removeAll(c1); //删除前c1: 孙悟空,100,50
Iterator it3 = c1.iterator();
while(it3.hasNext()){ //集合c1删除c2的全部元素后: 50
System.out.println(it3.next());
}
}
}
3.1.3 查找元素
private static void queryArrayListTest() {
System.out.println("ArrayList query test:");
ArrayList c1 = new ArrayList();
c1.add("孙悟空");
c1.add(100);
c1.add("猪八戒");
c1.add(50);
c1.add("唐僧");
c1.add(20);
System.out.println("集合的元素为:");
c1.forEach(o -> System.out.println(o));
System.out.println("集合包含:猪八戒?" + c1.contains("猪八戒"));
ArrayList c2 = new ArrayList();
c2.add("孙悟空");
c2.add(20);
System.out.println("集合C1 包含 集合c2?:" + c1.containsAll(c2));
}
3.1.4 遍历
方式1:使用Iterator遍历
System.out.println("ArrayList query test:");
ArrayList c1 = new ArrayList();
c1.add("李逵");
c1.add(100);
c1.add("宋江");
c1.add(50);
//使用Iterator遍历
System.out.println("集合元素:");
Iterator it1 = c1.iterator();
while (it1.hasNext()) {
System.out.println(it1.next());
}
方式2: 使用Labmbda foreach遍历
//使用foreach 遍历
c1.forEach(obj -> System.out.println(obj));
3.1.5 基于索引的函数
因为ArrayList是基于数据实现的,因此ArrayList类提供一些基于数组下标索引操作
请看下面的demo代码
- 在指定位置添加元素
private static void arrrayListIndexAPIDemo() {
System.out.println("ArrayList list api test:");
ArrayList c1 = new ArrayList();
c1.add("李逵");
c1.add(100);
c1.add("宋江");
c1.add(50);
c1.forEach(obj -> System.out.println(obj));
//位置1添加1个元素
c1.add(1,"卢俊义");
c1.forEach(obj -> System.out.println(obj));
}
- 在指定位置添加集合
ArrayList c2 = new ArrayList();
c2.add("吴用");
c2.add("公孙胜");
//指定位置添加集合
c1.add(2,c2);
c1.forEach(obj -> System.out.println(obj));
4 ArrayList泛型操作
Java是一个容器,可以包多个对象放入容器中,Java5之前会丢失容器中所有对象的类型,增加泛型后Java容器可以记住所有对象的数据类型。
下面的代码演示了泛型应用或不应用的区别。
private static void arrayListGenericTest() {
//未使用泛型
ArrayList name1 = new ArrayList();
name1.add("宋江");
name1.add("卢俊义");
name1.add(100); //可添加成功
//使用泛型
ArrayList<String> name2 = new ArrayList<>();
name2.add("宋江");
name2.add("卢俊义");
//name2.add(100); //报错,只能添加String类对象
}
5. ArrayList底层实现
5.1 . ArrayList数组创建
ArraryList是基于数组实现的,其内部定义一个Object数组用于存储各种元素:
transient Object[] elementData; // non-private to simplify nested class access
比如我们创建一个10个元素的ArrayList
ArrayList name = new ArrayList(10);
我们看下它的构造函数,构造函数会创建一个10个元素的Object[]
```java
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity]; //按我们指定大小创建一个数组
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
- ArrayList容量变换
ArrayList相对Array来说,其最大区别在于ArrayList容量可变,比如我先定义了1个3元素的ArrayList,然后又往里面添加了5元素,ArrayList会自动扩大其容量
我们看下ArrayList的 add()实现
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保Array容量够大
elementData[size++] = e;
return true;
}
5.2 ArrayList自动扩容方法
我们先看其自动扩容代码:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
下面是ArrayList数组自动扩容的算法:
6. 我的公众号
请关注我的公众号好,分享各种嵌入式,java开发原创技术文章。
7. 打赏
如果您觉得文章对你有帮助,打赏鼓励下。