1、Java容器:集合、数组对于多个数据进行存储操作的结构
说明:此时的存储只是内存层面的存储,不涉及硬盘持久化的存储(.txt、.jpg、.avi、数据库等)
2、数组在存储多个数据方面的特点:
1)一旦初始化,长度就不可变
2)一旦定义好,数组的元素类型不可变
3、数组在存储多个数据方面的缺点:
1)长度不可变
2)数组中提供的方法有限,对于增删改查操作不方便,效率低
3)没有现成获取数组元素个数的方法
4)对于无序存储没有解决方法
4、Collection接口:单列集合,用于存储多个对象
子接口:
List:存储有序、可重复数据
Set:存储无序、不可重复数据
Map接口:双列集合,用于存储多个key-value数据
5、Collection方法
void add(Object e)
:将元素e添加到集合中(为了调用contains更加方便,要重写添加类的equals()方法)
int size()
:获取添加的元素个数
void addAll(Collection coll)
:将另一个集合coll中的所有元素添加到当前集合中
void clear()
:清空当前集合元素
boolean isEmpty()
:判断当前集合是否为空(是否含有元素)
boolean contains(Object obj)
:判断当前集合中是否包含obj(调用的时equals()方法)
boolean containsAll(Collection coll)
:判断集合coll中所有元素是否都在当前集合中
boolean remove(Object obj)
:删除obj对象(中间会调用contains()方法),若有多个相同的,则只会删除一个
boolean removeAll(Collection coll)
:从当前集合中移除所有coll中的元素
void retainAll(Collection coll)
:把当前集合中的元素换为与coll集合的交集部分的元素
boolean equals(Object obj)
:判断当前集合和obj集合元素是否顺序、大小都相同
int hashCode()
:返回当前对象的哈希值
Object[] toArray()
:将当前集合转化为数组
Iterator<E> iterator()
:返回Iterator接口的实例,用于遍历集合元素
public class IteratorTest {
/**
* @Author: 果冻奶酪
* @Description: 集合元素的遍历操作,使用迭代器Iterator接口
* @Date: 16:40 2020/7/9
*/
@Test
public void demo(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tome"));
coll.add(false);
Iterator iterator = coll.iterator();
//方式一:
for (int i = 0;i < coll.size();i++){
System.out.println(iterator.next());
}
//方式二:
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
迭代器执行原理
迭代器iterator的remove()
方法:删除集合中的元素
注意:如果还未调用next()或在上一次调用next()之后已经调用过remove(),再次调用remove()方法会报IllegalStateException
foreach循环遍历:
JDK5.0之后提供了foreach循环迭代访问Collection和数组
遍历集合的底层调用iterator来完成操作
6、List接口
ArrayList:作为List接口的主要实现类;线程不安全,效率高;底层使用Object[] elementData
存储;
LinkedList:在进行增、删操作时效率比ArrayList高;底层使用双向链表存储
Vector:作为List最古老的实现类;线程安全,效率低;Object[] elementData
存储;
ArrayList源码分析:
JDK7.0版本:
ArrayList实例化:空参构造器:初始化一个长度为10的Object数组elementData
ArrayList添加操作:add(123):创建一个包装类Integer(123),放入Object[]数组中
数组容量满了:默认情况下,新数组扩容为原来的1.5倍(原有的数组长度>>1),将原来数组中的数据放到新的数组中;
JDK8.0版本:
ArrayList实例化:空参构造器:初始化Object[] elementData为{},并没有直接赋予长度
ArrayList添加操作:add(123):第一次调用时,才创建了长度为10的数组,并将数据放入数组中
数组容量满了:默认情况下,新数组扩容为原来的1.5倍(原有的数组长度>>1),将原来数组中的数据放到新的数组中
LinkedList源码分析:
LinkedList实例化:空参构造器:在内部声明一个Node类型的first、last变量以及int类型的size变量
LinkedList添加操作:add(123):新建一个Node类型的实体变量,将last变量放入Node的头节点,null放入尾节点,数据放入element中
常用方法:
void add(int index, Object ele)
:在index位置插入元素ele
boolean addAll(int index, Collection eles)
:从index位置开始将eles中的元素全部添加进来
Object get(int index)
:获取index位置的元素
int indexOf(Object obj)
:返回obj第一次在集合中出现的位置
int lastIndexOf(Object obj)
:返回obj最后一次在集合中出现的位置
Object remove(int index)
:移除index位置的元素,并将该元素返回
Object set(int index, Object obj)
:设置index位置的元素是obj
List subList(int fromIndex, int toIndex)
:返回从fromIndex开始到toIndex的子集合
7、Set接口
无序性:存储数据的位置无序性
不可重复性:添加的元素按equals方法判断是否相同
HashSet:Set接口主要实现类;线程不安全;可以存储null值
LinkedHashSet:HashSet子类;遍历内部数据时,可以按照添加顺序遍历;频繁的遍历操作,LinkedHashSet效率高于HashSet
TreeSet:可以按照添加对象的指定属性,进行排序
HashSet添加元素:
先调用元素a所在类的hashCode()方法计算哈希值,接着有哈希值算出元素a在数组中存放的下标位置,判断该位置上是否有元素:
①没有元素,该元素添加成功
②有元素b(或以链表形式存在多个元素),比较两者的哈希值:
1)如果不同,则添加成功;
2)如果相同,调用元素a的equals()方法::
如果返回true,则添加失败,如果为false,添加成功
在指定索引位置上多个数据的存储:
JDK7.0:元素a放在数组中,元素a指向元素b(尾插法)
JDK8.0:元素b放在数组中,元素b指向元素a(头插法)
LinkedHashSet:
优点:遍历效率优于HashSet
TreeSet:
①向其中添加数据,必须是相同类的对象
②必须指定类中的排序方式(自然排序或定制排序)
③自然排序中,比较两个对象是否相同的标准为compareTo()是否返回0
④定制排序中,比较两个对象是否相同的标准为compare()是否返回0
8、去除List中的重复值,要求尽量简单
将List类型的集合加到Set类型的集合中去,就可以过滤掉重复的数值。
注意:如果集合中只有数字的话不需要重写List中的equals()和HashSet中的HashCode()和equals()方法;但是如果是自定义类的话,就必须重写这三个方法
public List removeSame(List list){
HashSet set = new HashSet();
set.addAll(list);
return new ArrayList(set);
}
9、Map接口
HashMap:Map最主要的实现类;线程不安全,效率高;可以存储null的key和value
子类LinkedHashMap:保证在遍历Map元素时,可以按照添加的顺序进行遍历。原因:在原有的HashMap底层结构基础上,添加了一对指针,分别指向前后两个数据,对于频繁的遍历操作,此类执行效率高于HashMap
TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序。底层使用的时红黑树。
Hashtable:较老的实现类;线程安全,效率低;不可以存储null的key和value
子类Properties:常用来处理配置文件;key和value都是String类型;
HashMap底层:
数组+链表(JDK7.0及之前)
数组+链表+红黑树(JDK8.0)
Map结构理解:
key:无序、不可重复、使用Set存储所有的key ----->key所在的类要重写equals()和hashCode()
value:无序、可重复、使用Collection存储所有的value ----->key所在的类要重写equals()
一个键值对:key-value构成了一个Entry对象
Map中的entry:无序、不可重复、使用Set存储所有的entry
HashMap底层实现原理:
JDK7.0:
实例化:空参构造器:创建一个长度为16的Entry[]类型数组 Entry[] table
添加操作:put(key, value):闲调用key所在类的hashCode()计算哈希值,由此得到在Entry[] table中存放的位置;
如果该位置上为空,则直接放入;
如果该位置上有数据,则比较哈希值:如果哈希值不同,则放入;如果相同,则调用key的equals()方法,如果不相同,则直接放入,如果相同,key将相同的替换掉
扩容:当元素数量超过吞吐临界值且要存放的位置非空时,扩容。默认的时扩容为原来的2倍,并将原有的数据复制。
JDK8.0:
实例化:没有直接创建长度为16的数组Node[],而是将负载因子(loadFactor)赋值为0.75
首次调用put(Object obj):底层才会创建长度为16的数组Node[]
底层结构:数组+链表+红黑树;当数组的某一索引位置上的元素以链表形式存在的数据个数 > 8,且数组长度 > 64时,该位置上的元素改为红黑树存储。红黑树查找的时间复杂度为(logn)
默认数组长度(DEFAULT_INITIAL_CAPACITY):16
默认负载因子(DEFAULT_LOAD_FACTOR):0.75(浮点型)
扩容临界值:容量 * 负载因子
链表长度大于默认值,转化为红黑树(TREEIFY_THRESHOLD):8
Node被树化时最小的hash表容量(MIN_TREEIFY_CAPACITY):64
Map常用方法:
Object put(Object key, Object value)
:将指定key-value对添加(或替换)到map对象中
void putAll(Map m)
:将m中所有key-value对存放到当前map中
Object remove(Object key)
:移除指定key的key-value对,并返回value
void clear()
:清除当前map中所有数据
Object get(Object key)
:获取指定key对应的value
boolean containsKey(Object key)
:是否包含指定的key
boolean containsValue(Object value)
:是否包含指定的value
int size()
:返回map中key-value对的个数
boolean isEmpty()
:判断当前map是否为空
boolean equals(Object obj)
:判断当前map参数对象obj是否相等
Set keySet()
:返回所有key构成的Set集合
Collection values()
:返回所有value构成的Collection集合
Set entrySet()
:返回所有key-value对构成的Set集合
遍历map集合元素:
@Test
public void demo1(){
Map map = new HashMap();
map.put("AA", 123);
map.put(45, 123);
map.put("BB", 56);
//遍历所有的key集:keySet()
Set set = map.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//遍历所有的value集:valueSet()
Collection collection = map.values();
Iterator iterator1 = collection.iterator();
while (iterator1.hasNext()){
System.out.println(iterator1.next());
}
10、Collections工具类
Collections是一个操作List、Set、Map等集合的工具类
常用方法:
void reverse(List list)
:反转list中的元素顺序
void shuffle(List list)
:对list集合元素进行随机排序
void sort(List list)
:根据元素的自然顺序对指定的list集合元素升序排序
void sort(List list, Comparator)
:根据指定的Comparator产生的顺序对list集合元素进行排序
void sort(List list, int i, int j)
:将指定list集合中的i处元素和j处元素进行交换
Object max(Collection collection)
:根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection collection, Comparator)
:根据Comparator指定的顺序,返回给定集合中最大元素
Object min(Collection collection)
:根据元素的自然顺序,返回给定集合中的最小元素
Object min(Collection collection, Comparator)
:根据Comparator指定的顺序,返回给定集合中最小元素
int frequency(Collection collection, Object obj)
:返回指定集合中指定元素出现的个数
void copy(List dest, List src)
:将src中的内容复制到dest中
boolean replaceAll(List list, Object oldVal, Object newVal)
:使用新值替换list对象中旧值
copy方法的使用注意点
@Test
public void demo(){
List list = new ArrayList();
list.add(123);
list.add(23);
list.add(345);
list.add(456);
list.add(45);
List dest = Arrays.asList(new Object[list.size()]);
Collections.copy(dest, list);
System.out.println(dest);
}
Collections提供了多个synchronizedXxx()方法,该方法可以使线程不安全的集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题