Java集合01_ArrayList、LinkedList 和 Vector

Java集合

数组的优点:

元素连续分配空间,根据下标访问元素(随机访问效率高)

数组的局限性:

长度固定不变,不能自动扩容

删除和插入操作效率较低,需要移动大量的元素

元素的类型只能是一种

元素连续分配空间,在 heap 内存中必须找到连续的内存空间来存储数组(对内存要求较高)


为了解决数组的局限性,引入了容器类的概念

在这里插入图片描述

ArrayList

ArrayList 底层数据结构是数组,查询快,增删慢,线程不安全,效率高

add()size()isEmpty()
contains()indexOf()lastIndexOf()
iterator()remove()set()
get()toArray()clear()
public static void main(String[] args) {
    
    

	ArrayList<String> arrayList = new ArrayList<String>();
	arrayList.add("hello");
	arrayList.add("world");
	arrayList.add("BLU");
	arrayList.add("everyday");
	arrayList.add(3,"happy");
	
	System.out.println(arrayList);
	System.out.println("size:"+arrayList.size());
	System.out.println("是否为空集合:"+arrayList.isEmpty());
	System.out.println("位置为3的元素:"+arrayList.get(3));
	System.out.println("是否包含元素'BLU':"+arrayList.contains("BLU"));
	System.out.println("元素'BLU'所在位置:"+arrayList.indexOf("BLU"));
	System.out.println("元素'BLU'最后出现的位置:"+arrayList.lastIndexOf("BLU"));
	
	Iterator it = arrayList.iterator();
	while(it.hasNext()) {
    
    
		String s1 = (String) it.next();
		System.out.println("迭代器迭代:"+s1);
	}
	
	arrayList.remove("BLU");
	arrayList.remove(1);
	arrayList.set(0, "HELLO!");
	
	for(int i=0; i<arrayList.size();i++) {
    
    
		String s2 = (String) arrayList.get(i);
		System.out.println("for循环输出:"+s2);
	}

	for(String s : arrayList) {
    
    
		System.out.println("增强for循环输出:"+s);
	}
	
	Object[] array = arrayList.toArray();
	
	for (int i = 0; i < array.length; i++) {
    
    
		System.out.println("数组:"+array[i]);
	}
	
	arrayList.clear();
	System.out.println("size:"+arrayList.size());
	
}
[hello, world, BLU, happy, everyday]
size:5
是否为空集合:false
位置为3的元素:happy
是否包含元素'BLU':true
元素'BLU'所在位置:2
元素'BLU'最后出现的位置:2
迭代器迭代:hello
迭代器迭代:world
迭代器迭代:BLU
迭代器迭代:happy
迭代器迭代:everyday
for循环输出:HELLO!
for循环输出:happy
for循环输出:everyday
增强for循环输出:HELLO!
增强for循环输出:happy
增强for循环输出:everyday
数组:HELLO!
数组:happy
数组:everyday
size:0
containsAll()	本集合是否包含指定集合中的所有元素
addAll()		将指定集合中的所有元素添加到本集合
removeAll()		移除本集合中与指定集合的交集部分
retainAll()		移除本集合中指定集合的补集部分,保留交集
public static void main(String[] args) {
    
    

	ArrayList<String> arrayList1 = new ArrayList<String>();
	arrayList1.add("aaa");
	arrayList1.add("bbb");
	arrayList1.add("ccc");
	ArrayList<String> arrayList2 = new ArrayList<String>();
	arrayList2.add("ccc");
	arrayList2.add("ddd");
	arrayList2.add("eee");
	
	System.out.println("list1:"+arrayList1);
	System.out.println("list2:"+arrayList2);
	System.out.println("list1是否包含list2中的所有元素:"+arrayList1.containsAll(arrayList2));
	arrayList1.addAll(arrayList2);
	System.out.println("list1:"+arrayList1);
	arrayList1.removeAll(arrayList2);
	System.out.println("list1:"+arrayList1);
	arrayList1.add("ccc");
	arrayList1.retainAll(arrayList2);
	System.out.println("list1:"+arrayList1);

}
list1:[aaa, bbb, ccc]
list2:[ccc, ddd, eee]
list1是否包含list2中的所有元素:false
list1:[aaa, bbb, ccc, ccc, ddd, eee]
list1:[aaa, bbb]
list1:[ccc]

数组长度是有限的,而 ArrayList 可以存放任意数量的对象,长度不受限制,它是怎么实现的呢?

采用数组扩容的方式!

ArrayList 的默认初始容量大小为 DEFAULT_CAPACITY = 10

当 add() 时发现所需容量 minCapacity 超出了初始容量大小,将进入 grow(int minCapacity) 方法进行扩容,创建一个容量为 1.5倍旧容量 的新 ArrayList,将原数组数据拷贝至新数组

int newCapacity = oldCapacity + (oldCapacity >> 1);
elementData = Arrays.copyOf(elementData, newCapacity);

注:常见的写法会把引用声明为接口List类型

写法一:
ArrayList<String> h=new ArrayList<String>();

写法二(推荐):
List<String> mylist = new ArrayList<String>();
写法一用当前类作为引用类型,那么可以访问到ArrayList这个类中的所有公用方法。
写法二用接口List作为引用类型,那么通过list引用可以访问到接口中定义的方法。但是就无法调用的List接口以外的方法了。

设计模式中有:“代码尽量依赖于抽象,不依赖于具体”。
第一种形式就是依赖具体,第二种形式就是依赖于抽象。
代码依赖于抽象的好处是,代码可以方便替换。

例如,代码List list = new ArrayList();下面通过list来操作集合。
代码编写后发现集合使用的不准确,应该使用LinkedList,那么只要修改一行代码List list = new LinkedList();就可以了
因为List接口保证了调用的都是接口中的方法,而ArrayList与LinkedList都实现了List接口。
而如果当时用ArrayList list = new ArrayList()这种形式的话,那么list访问到的就可能是ArrayList里独有的方法而非List接口中的方法。
这样替换成LinkedList的时候就有可能需要修改很多的代码。

LinkedList

LinkedList:底层数据结构是链表,查询慢,增删快,线程不安全,效率高

LinkedList 和 ArrayList 一样实现了 list 接口,也同样拥有 list 接口的相关方法

此外 LinkedList 还实现了 Deque 接口,因此还拥有以下特有方法:

addFirst()addLast()
offerFirst()offerLast()
getFirst()getLast()
removeFirst()removeLast()

addFirst()offerFirst() 的区别是前者返回void,后者固定返回true
public static void main(String[] args) {
    
    
	LinkedList<String> list = new LinkedList<String>();
	list.add("hello");
	list.add("world");
	list.addFirst("Hi");
	list.addLast("BLU!");
	System.out.println(list);
	
	Iterator<String> it = list.iterator();
	while(it.hasNext()) {
    
    
		System.out.println(it.next());
	}
	
	System.out.println("头部元素:"+list.getFirst());
	System.out.println("尾部元素:"+list.getLast());
	list.removeFirst();
	list.removeLast();
	list.offerFirst("first");
	list.offerLast("last");
	System.out.println(list);
}
[Hi, hello, world, BLU!]
Hi
hello
world
BLU!
头部元素:Hi
尾部元素:BLU!
[first, hello, world, last]

ArrayList 和 LinkedList 的区别:

ArrayList 底层是数组,LinkedList 是基于链表的数据结构

ArrayList 查询快,而 LinkedList 查询需要移动指针,效率低

对于新增和删除操作,LinkedList 占优势,而 ArrayList 新增和删除需要移动数据,效率低


Vector

Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低

public static void main(String[] args) {
    
    

	Vector<String> list = new Vector<String>();
	list.addElement("hello");
	list.addElement("world");
	list.addElement("BLU");
	
	for(int i=0;i<list.size();i++) {
    
    
		System.out.println(list.elementAt(i));
	}
	
	Enumeration<String> elements = list.elements();
	
	while(elements.hasMoreElements()) {
    
    
		System.out.println(elements.nextElement());
	}
}
hello
world
BLU
hello
world
BLU

案例1:去除集合中字符串的重复值

思路1:创建一个新集合,遍历原集合,元素依次存入新集合,存入之前判断在新集合中是否已经存在
思路2:依次比较集合中的元素和集合后面的所有元素,发现有相同的值就把后面的元素删掉

思路1(注意这个 contains() 方法,它的底层是 equals() 方法,如果判断的是普通对象,则调用的是父类 Object 中的 equals 方法,而 Object 中的 equals 方法判断的是地址值是否相同,所以该普通对象需要重写 equals 方法):

public static void main(String[] args) {
    
    
	ArrayList<String> list = new ArrayList<>();
	list.add("a");
	list.add("b");
	list.add("c");
	list.add("d");
	list.add("c");
	list.add("c");
	list.add("e");
	list.add("b");
	ArrayList<String> newlist = new ArrayList<>();
	
	for(int i=0;i<list.size();i++) {
    
    
		if(!newlist.contains(list.get(i))) {
    
    
			newlist.add(list.get(i));
		}
	}
		
	System.out.println(newlist);
}
[a, b, c, d, e]

思路2(注意这个y减减,因为删除了一个元素后,后面的元素索引都会更改):

public static void main(String[] args) {
    
    
	ArrayList<String> list = new ArrayList<>();
	list.add("a");
	list.add("b");
	list.add("c");
	list.add("d");
	list.add("c");
	list.add("c");
	list.add("e");
	list.add("b");
	
	for(int i=0;i<list.size()-1;i++) {
    
    
		for(int j=i+1;j<list.size();j++) {
    
    
			if(list.get(i).equals(list.get(j))) {
    
    
				list.remove(j);
				j--;
			}
		}
	}
	
	System.out.println(list);	
		
}
[a, b, c, d, e]

猜你喜欢

转载自blog.csdn.net/BLU_111/article/details/108343047