集合大总结

介绍

集合可以动态保存任意多个对象,使用比数组较方便

提供了一系列方便的操作对象的方法:add,remove,set,get等

集合的框架体系

集合由Collection和Map接口组成,他们两个都继承了Iterable类。注意他们两个都没有直接的实现子类,而是通过他们的子类接口来实现的。

单列集合:Collection

双列集合:Map (K-V)

Collection接口实现类的特点

1,Collection接口实现的子类可以存放多个元素,每个元素都是Object

2,Collection的子类接口List,可以存放重复的元素,而Collection的子类接口Set则不可以

3,Collection的子类接口List是有序的,而Collection的子类接口Set是无序的

4,Collection接口没有直接的实现子类,是通过他的子类接口List和Set来实现的

常用方法

添加:add,addAll

删除:remove,removeAll

包含:contains,containsAll

获取元素个数:size

判断是否为空:isEmpty

清空:clear

List接口

实现类:ArrayList,LinkedList,Vector

1,List集合类中元素有序,且可重复

2,List集合中的每个元素都有下标

3,ArrayList和LinkedList都是线程不安全的,Vector线程安全

常用方法

添加:add,addAll

获取:get

查找:indexOf,lastIndexOf

删除:remove

替换:set

ArrayList的底层操作机制源码分析

ArrayList中维护了一个Object类型的数组elementDate

transient Object[] elementData: transient 表示瞬间,短暂的,表示改属性不会被序列号

ArrayList演示常用方法代码:

package com.java.test;

import java.util.ArrayList;

public class List_{
	public static void main(String[] args) {
		ArrayList a1 = new ArrayList();
		ArrayList a2 = new ArrayList();
		
		//添加:add,addAll
		a1.add("语文");
		a1.add("数学");
		a2.add("英语");
		a1.addAll(a2);
		System.out.println("a1="+a1);
		
		//获取:get
		System.out.println(a1.get(0));
		
		//替换:set
		a1.set(1, "物理");
		System.out.println("a1="+a1);
		
		//查找:indexOf返回第一次出现的索引,lastIndexOf返回最后一次出现的索引
		System.out.println(a1.indexOf("语文"));
		
		//删除:remove,removeAll
		a1.remove("数学");
		a1.removeAll(a2);
		System.out.println("a1="+a1);
		
		//包含:contains,containsAll
		System.out.println(a1.contains("语文"));
		
		//获取元素个数:size
		System.out.println(a1.size());
		
		//判断是否为空:isEmpty返回布尔值
		//清空:clear
		System.out.println(a1.isEmpty());
		a1.clear();
		System.out.println(a1.isEmpty());
		
	}
}
代码执行结果:
a1=[语文, 数学, 英语]
语文
a1=[语文, 物理, 英语]
0
a1=[语文, 物理]
true
2
false
true

ArrayList的扩容倍数

如果是无参,默认0,第一次10,第二次扩容按照1.5倍扩容

如果有参则每次直接按照1.5倍扩容

Vector

1,底层也是一个对象数组,protected Object[] elementData

2,线程安全

 Vector的扩容倍数

如果是无参构造器,默认10,满后就按照2倍扩容

如果指定大小,则每次直接按照2倍扩容

LinkedList

1,底层实现了双向链表和双端队列

2,可以添加任意元素(元素可以重复)

LinkedList的底层操作机制

1,LinkedList底层维护了一个双向链表

2,LinkedList中维护了两个属性first和last分别指向首节点和尾节点

3,每个节点(Node对象),里面又维护了prev,next,item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表

4,使用LinkedList的元素的添加和删除相对来说效率较高

ArrayList和LinkedList的比较

ArrayList是可变数组 增删的效率较低 改查的效率较高

LinkedList是双向链表 增删的效率较高 改查的效率较低

ArrayList和LinkedList都是线程不安全的

List接口的遍历方法:

1,Iterator迭代器

2,增强for循环

3,for循环

package com.java.test;

import java.util.ArrayList;
import java.util.Iterator;

public class List_{
	public static void main(String[] args) {
		ArrayList a1 = new ArrayList();
		a1.add(10);
		a1.add(100);
		a1.add(1000);
		
		//1,Iterator迭代器
		Iterator iterator = a1.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}

		//2,增强for循环
		for(Object i:a1){
			System.out.println(i);
		}
		
		//3,for循环
		for(int i = 0 ; i < a1.size() ; i++) {
			System.out.println(a1.get(i));
		}
	}
}

Set接口

实现类:HashSet,LinkedHashSet,TreeSet

1,无序的,没有下标

2,不允许重复元素,最多包含一个null

3,取出的顺序的顺序虽然不一定是添加的顺序,但是他是固定的

4,Set接口的常用方法和List一致

HashSet

1,实现了Set接口

2,HashSet实际上是HashMap

3,可以存放null值,但是只能有一个null

4,HashSet不保证元素是有序的,取决于hash后,再确定索引的结构

5,不能有重复的元素

HashSet的添加机制

1,HashSet底层是HashMap

2,添加一个元素时,先得到hash值,会转成索引值

3,找到table数组,看这个索引位置是否以及存放的有元素,如果没有,直接加入,如果有,调用equals比较,如果相同则放弃添加,如果不相同则添加到其链表后

6,再Java8中,如果一条链表的元素个数超过8并且table的大小大于等于64就会进行树化(红黑树)

LinkedHashSet

1,LinkedHashSet时HashSet的子类

2,LinkedHashSet底层是一个LinkedHashMap(为HashMap的子类),底层维护了一个数组+双向链表,LinkedHashSet有head和tail,每个节点有before和after属性

3,LinkedHashSet根据元素的hashCode值来确定元素的储存位置,同时使用链表维护元素的次序,是的元素看起来是以插入顺序保存的。即添加的顺序和取出的顺序一样

4,LinkedHashSet不允许添加重复元素

5,添加第一次时,直接将数组table扩容到16,数组是HashMap$Node[],存放的节点类型时LinkedHashMap$Entry

TreeSet

1,底层就是TreeMap

2,当使用无参构造器创建TreeSet时,仍然是无序的

3,当希望按照字符串大小来排序:

使用TreeSet提供的一个构造器,可以传入一个比较器(匿名内部类)并指定排序规则

如果匿名内部类里面的compare方法比较字符串长度则如果有两个长度相同的String不可重复添加

Set接口的遍历方法:

1,Iterator迭代器

2,增强for循环

3,Set是无序的没有索引的,所以遍历时不可用for循环遍历

package com.java.test;

import java.util.HashSet;
import java.util.Iterator;

public class Set_{
	public static void main(String[] args) {
		HashSet a1 = new HashSet();
		a1.add(10);
		a1.add(100);
		a1.add(1000);
		
		//1,Iterator迭代器
		Iterator iterator = a1.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}

		//2,增强for循环
		for(Object i:a1){
			System.out.println(i);
		}
	}
}

Map接口

Map与Collection并列存在,用于保存具有映射关系的数据:K-V

实现类:Hashtable,HashMap,TreeMap

常用方法

添加:put

删除:remove

获取值:get

获取元素个数:size

判断是否为空:isEmpty

清空:clear

包含:containsKey

Map接口的遍历方法

1,通过keySet获取所有的键,再使用get方法获取值

2,通过entrySet来获取K-V

package com.java.test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Map_{
	public static void main(String[] args) {
		HashMap h1 = new HashMap();
		h1.put("语文", 100);
		h1.put("数学", 90);
		h1.put("英语", 110);
		
		//1,通过keySet获取所有的键,再使用get方法获取值
		Set keyset = h1.keySet();
		
		//(1)增强for循环
		for(Object key : keyset){
			System.out.println(key+"-"+h1.get(key));
		}
		
		//(2)Iterator迭代器
		Iterator iterator =  keyset.iterator();
		while(iterator.hasNext()){
			Object key = iterator.next();
			System.out.println(key+"-"+h1.get(key));
		}
		
		//2,通过entrySet来获取K-V
		Set entryset = h1.entrySet();
		
		//(1)增强for循环
		for(Object entry : entryset){
			Map.Entry m = (Map.Entry) entry; 
			System.out.println(m.getKey()+"-"+m.getValue());
		}
		
		//(2)Iterator迭代器
		Iterator iterator1 =  entryset.iterator();
		while(iterator1.hasNext()){
			Object entry = iterator1.next();
			Map.Entry m = (Map.Entry) entry;
			System.out.println(m.getKey()+"-"+m.getValue());
		}
	}
}

HashMap

1,Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中(节点HashMap$Node实现Map$Entey接口)

2,Map中的key不允许重复但value可以重复,当重复添加key时就等价于替换value

3,HashMap中的key和value可以为null

4,常用String类作为Map的key

5,key和value之间存在单向一对一关系,即可以通过指定的key总能找到对应的value

6,Map存放数据的K-V时放在一个Node中的,Node内部类实现了Entry接口

7,线程不安全

HashMap演示常用方法代码:

package com.java.test;

import java.util.HashMap;

public class Map_{
	public static void main(String[] args) {
		HashMap h1 = new HashMap();
		
		//添加:put
		h1.put("语文", 100);
		h1.put("数学", 90);
		h1.put("英语", 110);
		
		//删除:remove
		h1.remove("语文");
		
		//获取值:get
		System.out.println(h1.get("数学"));
		
		//获取元素个数:size
		System.out.println(h1.size());
		
		//判断是否为空:isEmpty
		//清空:clear
		System.out.println(h1.isEmpty());
		h1.clear();
		System.out.println(h1.isEmpty());
		
		//包含:containsKey
		System.out.println(h1.containsKey("英语"));
	}
}
代码执行结果:
90
2
false
true
false

Hashtable

1,存放的是键值对

2,Hashtable的键值都不可以为null,否者会抛出NullPointerException异常

3,Hashtable使用方法基本上和HashMap一样

4,线程安全

Hashtable的扩容机制

底层数组Hashtable$Entry[]初始大小为11

临界值threshold 8 = 11 * 加载因子(创建对象时默认为0.75)0.75

当cound >= threshold时 扩容到当前容量的两倍加一

Properties类继承自Hashtable类

1,Properties也是使用一种键值对的形式保存数据

2,他的使用特点和Hashtable类似

3,Properties还可以用于xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改

4,工作后xxx.properties文件通常作为配置文件

HashMap和Hashtable的对比

HashMap线程不安全,效率高,键值都可以为null

Hashtable线程安全,效率低,键值都不可以为null

TreeMap

1,当使用无参构造器创建TreeMap时,仍然是无序的

2,当希望按照key(String)的大小来排序

3,使用TreeSet提供的一个构造器,可以传入一个比较器(匿名内部类)并指定排序规则

如果匿名内部类里面的compare方法比较字符串长度则如果有两个长度相同的key(String)不可重复添加,如果添加则替换

集合选型规则

在开发中,选择声明集合实现类,取决与业务操作特点分析:

先判断存储的类型(一组对象或一组键值对)

        一组对象:Collection接口

                允许重复List

                        线程不安全

                                增删多LinkedList底层维护了一个双向链表

                                查改多ArrayList底层维护Object类型的可变数组

                        线程安全Vector

                不允许重复Set

                        无序HashSet底层是HashMap,维护了一个哈希表:数组+链表+红黑树

                        排序TreeSet

                        添加和取出的顺序一致LinkedHashSet维护数组+双向链表

        一组键值对:Map接口

                键无序HashMap底层是哈希表:数组+链表+红黑树

                键排序TreeMap

                键添加和取出的顺序一致LinkedHashMap

                读取文件Properties

Collections工具类

1,Collections是一个操作List,Set和Map集合的工具类

2,Collections中提供了一系列静态的方法对集合元素进行排序,查询,和修改等操作

排序操作

反转:reverse(List)

随机排序:shuffle(List)

自然顺序排序:sort(List)

匿名内部类规则排序:sort(List,Comparator)

元素交换:swap(List , int , int)

最大值max(List)

匿名内部类规则取最大值max(List,Comparator)

返回集合中指定元素的出现次数frequency(Collection , Object)

复制:copy(Collection c1 , Collection c2) copy前需要数组的大小大于或等于源数组的长度

替换:replaceAll(Collection c1 , Object oldVal , Object newVal)

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值