- 概述
1. 集合、数组都是对多个数据进行存储操作的结构,简称Java容器【主要指的是内存层面的存储,不涉及到持久化的存储(.txt .jpg .avi 数据库)】
2. 数组在存储多个数据方面的特点
> 一旦初始化以后,长度就确定了
> 数组一旦定义好,其元素的类型也确定了
- 集合框架
a) Collection接口:单列集合,用来存储一个个的对象
i. List:存储有序的、可重复的数据→动态数组
ArrayList、LinkedList、Vector
ii. Set:存储无序的、不可重复的数据→即数学中的集合
HashSet、LinkedHashSet、TreeSet
b) Map接口:双列集合,用来存储一对对数据(键值对)
HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
- Colletion接口中方法的使用
add(Object obj):将元素obj加入到集合中
size():获取添加的元素的个数
addAll(Collection c1):将c1中的元素添加到当前集合中
clear():清空集合元素
isEmpty():判断当前集合是否为空【集合内是否有元素】
contains(Object obj):判断当前集合中是否包含obj
【向Cllection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals(),让这个类的equals()比较对象的值,如果不重写相当于是Object()中得到equals(),也就是==,比的是地址】
c0.add(new Person("Jack",20));
System.out.println(c0.contains(new Person("Jack",20))); //True
containsAll(Collection c1):判断c1中的元素是否都在当前集合中
remove(Object obj):从当前集合中删除obj,可以获取返回值,找到obj返回1,否则0
removeAll(Collection c1):从当前集合中删除其和c1的共同元素
retainAll(Collection c1):获取当前集合和c1的交集,将当前集合修改为此交集
equals(Object obj):要想返回true,需要当前集合和形参集合的元素都相同
hashCode():返回当前对象的哈希值
toArray():集合à数组
Object[] arr = c0.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
数组→集合
List<String> list = Arrays.asList(new String[]{"AA","BB"});
iterator():返回Iterator接口的示例,用于遍历集合元素。放在IteratorTest.java中测试
Iterator迭代器
hasNext():判断是否还有下一个元素
next():指针下移,将下移后集合位置上的元素返回
Iterator iterator = c0.iterator();
while (iterator.hasNext()){//输出c0所有元素
System.out.println(iterator.next());
}
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标在集合的第一个元素之前
内部定义了remove(),可在遍历的时候,删除集合中的元素。此remove()不同于集合中的remove()【如果还未调用next()或在上一次调用next()之后已经调用了remove(),再调用remove()会出现异常IllegalStateException】
foreach(增强for循环)
for(集合元素的类型 局部变量:集合对象)【遍历集合】
for (Object obj : c0) {
System.out.println(obj);
}
for(数组元素的类型 局部变量:数组对象)【遍历数组】
for (int i:arr)
System.out.println(i);
}
新特性(可用来进行遍历):
list.forEach(str-> System.out.println(str))
或list.forEach(System.out::println)
遍历方法
List<String> list = Arrays.asList("aaaa","bbbb");
//for循环
for (int i=0;i< list.size();i++){
System.out.println(list.get(i));
}
增强for循环
for(String str : list){
System.out.println(str);
}
list.forEach(str-> System.out.println(str))
或
list.forEach(System.out::println)
迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
List接口
ArrayList:
List接口的主要实现类,线程不安全,效率高;底层使用Object[] elementData存储
jdk 7中:
ArrayList list = new ArrayList();
底层创建了长度是10的Object[]数据elementData
如果加入新元素超出长度,则扩容
默认情况:扩容为原来容量的1.5倍,再将原数组的内容复制到新数组中
ArrayList list = new ArrayList(int capacity);
通常使用带参数的构造器↑
jdk 8中:
底层Object[] elementData初始化为{} 没有创建长度是10的数组
当第一次调用add()时,才创建了长度是10的数组并添加元素进数组。后续和jdk 7 相同
LinkedList
对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
Vector:
古老实现类,线程安全的,效率低
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组
List接口中的方法
常用方法
增:add(Object obj)
删:remove(int index)/remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index,Object ele)
长度:size()
遍历:①Iterator迭代器
-
- foreach
- 普通循环
Set接口
以HashSet为例
- 无序性:不等于随机性。由哈希值决定数据存放位置。
- 不可重复性:保证添加的元素按照equals()判断时,不能返回true。相同元素只能存储一个
HashSet:作为Set接口的主要实现类;线程不安全;可以存储null值
LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可按照添加的顺序遍历【双向链表】
TreeSet:可以按照添加对象的指定属性,进行排序
要求: 向Set中添加的数据,其所在类一定要重写hashCode()和equals()
重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
添加元素的过程:以HashSet为例:
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:
- 如果此位置上没有其他元素,添加元素a
- 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a和元素b的哈希值
- 哈希值不同,添加元素a
- 哈希值相同,调用元素a所在类的equals()
- equals()返回true,已有相同元素,不添加a
- equals()返回false,添加元素a
TreeSet
- 向TreeSet中添加的数据,要求是相同类的对象
- 两种排序方式:自然排序(实现Comparable接口) 和 定制排序
- 自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,,不再是equals()
- 定制排序中,比较两个对象是否相同的标准为:compare ()返回0,,不再是equals()
Map接口
双列数据,存储key-value的数据
HashMap:作为Map的主要实现类;线程不安全,效率高;可存储null的key-value
LinkedHashMap:保证在遍历map元素是,可以按照添加的顺序实现【在原有的底层结构上,添加了一对指针,指向前后】
对于频繁的遍历操作,此类执行效率高于HashMap
TreeMap:保证按照添加的key-value进行排序,实现排序遍历。此时考虑key的自然排序或定制排序【向TreeMap中添加key-value,要求key必须是由同一个类创建的对象】
底层使用红黑树
HashTable:古老实现类;线程安全,效率低;不可存储null的key-value
Properties:常用来处理配置文件,key和value都是String类型
Map结构的理解:
Map中的key是无序的、不可重复的,使用Set存储所有的key;àkey所在的类要重写equals()和hashCode()(以HashMap为例)
value是无序的、可重复的,使用Collection存储所有value;àvalue所在的类要重写equals()
一个键值对key-value构成一个Entry对象,entry无序、不可重复,使用Set存储所有的entry
【当添加key-value时,计算key的哈希值,如果该位置上有数据且与key相等,则用value覆盖之前存储的数据】
Map中的方法
常用方法
增:put(Object key,Object value)
删:remove(Object key)
改:put(Object key,Object value)
查:get(Object obj)
长度:size()
遍历:keySet()/values()/entrySet()
遍历所有的key集:keySet()
Set set = map.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
遍历所有的value集:values()
Collection values = map.values();
for (Object obj:values){
System.out.println(obj);
}
遍历所有的key-values【需要强转】
Set entrySet = map.entrySet();
Iterator iterator1 = entrySet.iterator();
while (iterator1.hasNext()){
Object obj = iterator1.next();
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry); //AA=123
System.out.println(entry.getKey()+ "--->"
+entry.getValue());//AA--->123
}
Collections工具类
操作Collection和Map的工具类