一、Java集合框架概述:
1.1 Collection接口继承树
JDK提供的集合API位于java.util包内。
Map接口继承树
1.2 Collection接口方法
Collection 接口
Collection
接口是
List
、
Set
和
Queue
接口的父接口,该接口里定义的方法既可用于操作 Set
集合,也可用于操作
List
和
Queue
集合。
JDK不提供此接口的任何直接实现,而是提供更具体的子接口
(
如:
Set
和
List)实现。
在
Java5
之前,
Java
集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object
类型处理;从
JDK 5.0
增加了
泛型
以后,
Java
集合可以记住容器中对象的数据类型。
Collection 接口方法
1.3 Iterator迭代器接口
使用 Iterator
接口遍历集合元素
Iterator对象称为迭代器
(
设计模式的一种
)
,主要用于遍历
Collection
集合中的元素。
GOF给迭代器模式的定义为:提供一种方法访问一个容器
(container)
对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。
类似于“交车上的售票员”、“火车上的乘务员”、“空姐”。
Collection接口继承了
java.lang.Iterable
接口,该接口有一个
iterator()
方法,那么所有实现了Collection
接口的集合类都有一个
iterator()
方法,用以返回一个实现Iterator接口的对象。
Iterator 仅用于遍历集合
,
Iterator
本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
集合对象每次调用iterator()
方法都得到一个全新的迭代器对象
,默认游标都在集合的第一个元素之前。
Iterator接口的方法
在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且
下一条记录无效,直接调用 it.next() 会抛出 NoSuchElementException 异常。
二、List接口
2.1 List接口概述
鉴于Java
中数组用来存储数据的局限性,我们通常使用
List
替代数组。
List集合类中
元素有序、且可重复
,集合中的每个元素都有其对应的顺序索引。
List
容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
JDK API中
List
接口的实现类常用的有:
ArrayList
、
LinkedList
和
Vector。
2.2 List接口方法
2.3 ArrayList
ArrayList
是
List
接口的典型实现类、主要实现类。
本质上,
ArrayList
是对象引用的一个
”
变长
”
数组。
ArrayList
的
JDK1.8
之前与之后的实现区别?
JDK1.7:
ArrayList
像饿汉式,直接创建一个初始容量为
10
的数组。
JDK1.8:
ArrayList
像懒汉式,一开始创建一个长度为
0
的数组,当添加第一个元素时再创建一个始容量为10
的数组。
Arrays.asList(…)
方法返回的
List
集合,既不是
ArrayList
实例,也不是Vector 实例。
Arrays.asList(…)
返回值是一个固定长度的
List。
ArrayList 就是一个动态的数组。
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高。
2.3.1 ArrayList 构造方法
2.3.2 ArrayList 方法
public class Test01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("a");
System.out.println(list);
System.out.println(list.get(1));
System.out.println("list集合遍历:");
/*
for (int i = 0;i< list.size();i++){
String s = list.get(i);
System.out.println(s);
}
*/
//增强for循环
for (String s :list){
System.out.println(s);
}
}
}
另一个博客里写有ArrayList这里就不再讲述了。
2.4 List实现类之二:LinkedList
对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高。
LinkedList基于链表的存储结构。
LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:
prev变量记录前一个元素的位置。
next变量记录下一个元素的位置。
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
2.4.1 LinkedList 构造方法
2.4.2 LinkedList 方法
ArrayList和LinkedList的异同
二者都线程不安全,相对线程安全的
Vector
,执行效率高。
此外,ArrayList
是实现了基于动态数组的数据结构,
LinkedList
基于链表的数据结构。对于随机访问get
和
set
,
ArrayList
觉得优于
LinkedList
,因为
LinkedList
要移动指针。对于新增和删除add(
特指插入
)
和
remove
,
LinkedList
比较占优势,因为
ArrayList
要移动数据。
三、Set接口
Set接口是Collection的子接口,set接口没有提供额外的方法
Set
集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。
Set
判断两个对象是否相同不是使用
==
运算符,而是根据
equals()
方法
3.1 Set实现类之一:HashSet
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
HashSet
按
Hash
算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
HashSet 具有以下特点:
不能保证元素的排列顺序
HashSet 不是线程安全的
集合元素可以是
null
HashSet
集合判断两个元素相等的标准
:
两个对象通过
hashCode()
方法比较相等,并且两个对象的 equals()
方法返回值也相等。
对于存放在
Set
容器中的对象,
对应的类一定要重写
equals()
和
hashCode(Object
obj)
方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
向 HashSet 中添加元素的过程:当向 HashSet 集合中存入一个元素时, HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象HashSet 底层数组中 的存储位置。(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布,该散列函数设计的越好)。如果两个元素的hashCode() 值相等,会再继续调用 equals 方法,如果 equals 方法结果为true ,添加失败;如果为 false ,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过 链表的方式 继续链接。如果两个元素的 equals() 方法返回 true ,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
重写
hashCode()
方法的基本原则
在程序运行时,同一个对象多次调用 hashCode()
方法应该返回相同的值。
当两个对象的 equals()
方法比较返回
true
时,这两个对象的
hashCode()方法的返回值也应相等。
对象中用作 equals()
方法比较的
Field
,都应该用来计算
hashCode
值。
3.1.1 HashSet 构造方法
3.1.2 HashSet 方法
public class Test01 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("x");
set.add("y");
set.add("z");
set.add("x");
System.out.println(set);
System.out.println("set集合的遍历:");
//set集合用迭代器来遍历
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
}
}
四、Map接口
Map接口概述
Map与
Collection
并列存在。用于保存具有
映射关系
的数据
:key-value。
Map
中的
key
和
value
都可以是任何引用类型的数据。
Map
中的
key
用
Set
来存放,
不允许重复
,即同一个
Map
对象所对应的类,须重写hashCode()
和
equals()
方法。
常用
String
类作为
Map
的“键”。
key
和
value
之间存在单向一对一关系,即通过指定的
key
总能找到唯一的、确定的 value。
Map
接口的常用实现类:
HashMap
、
TreeMap
、
LinkedHashMap
和Properties。其中,
HashMap
是
Map
接口使用频率最高的实现类。
4.1 Map 接口:常用方法
4.2 Map实现类之一:HashMap
HashMap是 Map 接口使用频率最高的实现类。
允许使用
null
键和
null
值,与
HashSet
一样,不保证映射的顺序。
所有的
key
构成的集合是
Set:
无序的、不可重复的。所以,
key
所在的类要重写:equals()和
hashCode()。
所有的
value
构成的集合是
Collection:
无序的、可以重复的。所以,
value
所在的类要重写:equals()。
一个
key-value
构成一个
entry。
所有的
entry
构成的集合是
Set:
无序的、不可重复的。
HashMap
判断两个
key
相等的标准
是:两个
key
通过
equals()
方法返回
true
,hashCode 值也相等。
HashMap
判断两个
value
相等的标准
是:两个
value
通过
equals()
方法返回
true
。
4.2.1 HashMap 构造方法
4.2.2 HashMap 方法
五、Collections工具类
Collections
是一个操作
Set
、
List
和
Map
等集合的工具类。
Collections
中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法。
排序操作
:
(均为
static
方法)
reverse(List):
反转
List
中元素的顺序
shuffle(List):
对
List
集合元素进行随机排序
sort(List):
根据元素的自然顺序对指定
List
集合元素按升序排序
sort(List,
Comparator)
:
根据指定的
Comparator
产生的顺序对
List
集合元素进行排序
swap(List,
int
,
int)
:
将指定
list
集合中的
i
处元素和
j
处元素进行交换
Collections
常用方法:同步控制
Collections
类中提供了多个
synchronizedXxx()
方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。