JAVA基础 容器
我们之前了解了数组,数组是一个存储多个是相同数据类型的有序集合,是一个定长的引用数据类型,根据索引操作数组效率高。
而我们今天说的容器是可以变长,并且操作灵活,能够存储多个不同数据类型的数据。注意存储的数据只能是引用数据类型的,因此如果想要存储基本数据类型,就要改成相应的引用数据类型。
Collection
/ \
List Set
/ \ / \
ArrayList LinkedList TreeSet HashSet
Map
/ \
HashMap TreeMap
Collection 是容器体系的上层接口
可以使用 类 来实现Collection接口,也可以用Collection接口的多态。
其中ArrayList 就是一个有Collection接口的实现类,是有序可以重复的。 Collection col = new ArrayList();//接口多态
常用方法
add 添加
col.add(“zhangsan”);
addAll() 可以将集合的元素添加到容器中。
clear 清除
从此集合中删除所有元素
//col.clear();
isEmpty()
如果此集合不包含任何元素,则返回 true 。是否为空
contains(Object o)
是否包含指定的元素,是返回true
containsAll 是否包含指定集合
remove 移除
从此集合中移除指定元素的单个实例(如果存在
removeAll 删除包含指定集合的元素
retainAll
仅保留此集合中包含在指定集合中的元素。交集
toArray()
返回包含此集合中所有元素的数组。
遍历
for each 遍历
for(Object obj:col2){
System.out.println(obj);
}
iterator 迭代器遍历
//iterator() 返回此集合中元素的迭代器。
//1.获取操作某一个集合迭代器
Iterator it = col.iterator();
//2.hashNext() 是否存在下一个元素
while(it.hasNext()){
//3.获取下一个元素next()
System.out.println(it.next());
}
List
是列表的意思,也就是有顺序可以重复的。
新增功能: 一些根据索引操作的方法 of(…)创建集合的同时添加数据,集合不可变 subList()
遍历方式: foreach,iterator迭代器, for ,列表迭代器 ListIterator
List运用
List list = new ArrayList<>();
<泛式> 尖括号中的是泛式,是引用数据类型,默认是Object 。自定义引用类型不能省略。
规范存储数据的数据类型,泛型可以提高代码的可读性,稳定性,帮助检查存储数据的类型。
add
list.add(1);//默认是添加到结尾的
list.add(1,10);//第一个是索引,第二个是值
remove
删除索引的值
indexOf,clear,equals,isEmpty,replace
indexOf返回第一个出现的索引
clear清除
equals比较
isEmpty是否为空
replace替换
get
返回此列表中指定位置的元素。
of
返回包含元素的不可修改列表List。
size
返回列表的元素数
toArray
以适当的顺序(从第一个元素到最后一个元素)返回包含此列表中所有元素的数组。
subList
返回指定区间的List。
遍历
主要讲下 for 和 列表迭代器 ListIterator。另外的2种和Collection中的基本相同。
for循环遍历
//i作为集合的索引
for(int i=0;i<= list.size()-1;i++){
System.out.println(ls.get(i));
}
ListIterator遍历
//1.获取操作这个集合的迭代器
ListIterator<String> lt = list.listIterator();
//2.判断是否存在下一个元素
while(lt.hasNext()){
String str = lt.next(); //因为存在泛型,素有可以使用String类型接收
System.out.println(str);
}
ArrayList
底层数据结构: 数组|可变数组 (数组:内存中一段连续的内存空间) (Object[] elementData)
优点 : 查询,遍历效率高(根据索引)
缺点 : 添加,删除数据效率较低,创建新数组,数据拷贝
应用场景 : 大量做查询的时候,少量做修改的时候,适合使用ArrayList存储数据
ArrayList() 构造一个初始容量为10的空列表。 *** ->不确定集合中存储多少数据,使用
ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。 ->当确定集合中存储数据的个数范围的时候,可以选择使用
ArrayList(Collection<? extends E> c) 按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。
方法:操作内容,根据索引进行操作
扩容:根据空构造构建ArrayList,初始默认空数组,第一次添加数据默认容量为10,存不下了才扩容,每次扩容原容量的1.5倍
Vector 向量 与 ArrayList 区别
共同点: 底层结构也是数组,特点一样
不同定:
1)Vector线程安全,ArrayList线程不安全
2)扩容:Vector每次扩容原容量的2倍 而ArrayList是1.5倍,所以ArrayList更有利于节省内存
使用:
//创建集合
ArrayList list = new ArrayList();
方法和List差别不大。
Vector
Vector 向量 与 ArrayList 区别
共同点: 底层结构也是数组,特点一样
不同定:
1)Vector线程安全,ArrayList线程不安全
2)扩容:Vector每次扩容原容量的2倍 而ArrayList是1.5倍,所以ArrayList更有利于节省内存
**LinkedList **
链表。有序可重复,底层是双向链表结构。 增删效率高,但查询效率低,一般用在大量做增删,少量做查询的场景。
方法: 新增了一些操作链表头尾的方法
使用
LinkedList list = new LinkedList<>();
addFirst ,addLast
addFirst 在列表的开头插入指定元素
addLast 将指定的元素追加到此列表的末尾。
element,peekFirst
element() 检索但不删除此列表的头部(第一个元素)
peekFirst() 检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。
Set
List 与 Set之间的区别:
都是Collection接口的子接口,可以存储多个数据,但是每个数据只能为一个值
都继承了Collection的能力
List 有序可重复,拥有一些可以根据索引操作的方法
Set 无序不可重复
去重逻辑: e1.equals(e2)的返回值决定,和最多一个null元素。
TreeSet
TreeSet --> TreeMap --> TreeSet是由TreeMap维护的,是Map的key
底层结构: 红黑树结构
特点: 数据会升序排序,去重
使用:TreeSet tree = new TreeSet<>();
tree.add(5);
注意
TreeSet 存储数据是默认升序排序
但是要求: 数据是能够比较大小的
存储数据,可以指定当前使用哪种比较规则(外部比较器),如果没有指定默认使用找内部比较规则(内部比较器),如果内部外部都没有就抛出异常
ClassCastException : 类型转换异常
去重和排序都是根据比较负责决定
Set遍历方式都与Collection方式相同
内部比较器
Comparable 自然排序|内部比较器|自然比较器|默认比较规则:
此接口对实现它的每个类的对象强加一个总排序。 这种排序被称为类的自然顺序 ,类的compareTo方法被称为其自然比较方法 。
使用方式:一个自定义的引用数据类型实现Comparable接口,重写compareTo,在重写方法中指定当前类型数据的比较规则
注意: 内部比较器属于硬编码编程习惯,每次要修改都要修改javabean类的源码,不够灵活,没办法在不同的业务员下根据不同的规则比较
public class Employee implements Comparable<Employee>{
//............代码块..........
@Override
public int compareTo(Employee o) {
//return this.height-o.height; //升序
return o.height-this.height; //降序
}
外部比较器
外部比较器|定制排序
比较规则定义值javabean类的外部
实现方式: 实现类实现Compatator接口,重写int compare(T o1, T o2) 比较它的两个参数的顺序。定制比较规则
推荐使用: 软编码习惯
//外部比较器,比较员工类,根据员工的姓名比较员工信息
class Demo implements Comparator<Employee>{
@Override
public int compare(Employee o1, Employee o2) {
return o2.getName().compareTo(o1.getName());
}
}
外部比较器: 通过Comparator接口的实现类重写compare方法定义比较规则,这个实现类没有类原本自己的作用,可以选择使用匿名内部类简化
lambda可以用来简化匿名内部类:
前提: 接口为函数式接口@FunctionalInterface
(参数列表)->{重写的方法体}
注意: 要对自定义引用数据类型进行 排序的位置,都需要指定比较规则|比较器问题
HashSet
HashSet ->是由HashMap维护的
多个数据每个数据是单个值, 无序,去重
底层: 哈希表(数组+链表+红黑树)
优点: 查询,增删效率高
缺点: 无序
去重: 需要类型中重写hashcode和equals方法,根据对象的内容计算,而非地址计算hashcode和equals
hashcode和equals之间的规律特点:
equals相等的hashcode肯定相等
hashcode相等的equals不一定相等
使用:Set set = new HashSet<>();
set.add(“张三”);
Map
Map<K,V> 接口
存储键值对类型的数据
K-V(键值对) 之间存在映射关系
K : 唯一的,无序的 --> Set
V : 可重复,无序的 --> Collection
K,V 都可以为任意数据类型
注意:
Map的去重,根据key做去重的
添加数据,如果key相同,value会覆盖
key,与 value都可以赋值为null
一个key只能对应一个value,但是可以把多个value值放入集合中,一个key对应一个集合
使用:
HashMap<String,Integer> map = new HashMap<>();
//V get(Object key) 返回指定键映射到的值,如果此映射不包含键的映射,则返回 null 。
//V put(K key, V value) 将指定的值与此映射中的指定键相关联(可选操作)。
//containsKey(Object key) 如果此映射包含指定键的映射,则返回 true 。
//containsValue(Object value) 如果此映射包含指定 值 的映射,则返回 true
//remove(Object key) 删除key为参数的键值对,返回value
遍历:
1.keySet() 返回当前map集合中的所有键值对的key
Set<String> set = map.keySet();
for(String key:set){
System.out.println("key = "+key+",value = "+map.get(key));
map.put(key,12);
}
2.values() 获取当前集合中所有键值对的value值
Collection<Integer> col = map.values();
Iterator<Integer> it = col.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
3.entrySet() 把map中的每一个键值对返回成为一个Map.Entry类型的数据放入set集合
//Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射的Set视图。
Set<Map.Entry<String,Integer>> set2 = map.entrySet();
for(Map.Entry<String,Integer> entry:set2){
System.out.println(entry.getKey()+"-->"+entry.getValue());
}
HashMap
底层实现: 哈希表
特点: 查询,增删效率高
初始容量: 内部位桶数组的大小 16
加载因子loadFactor : 0.75
threshold :临界值(阀值) = 容量*加载因子
size: 集合中存储键值对的个数
扩容: 每次扩容原容量2倍
可以存储null值作为key和value,但线程不安全(不同步)。
Hashtable
线程安全的Hash表,与HashMap非常像
Hashtable是同步的|线程安全的。 如果不需要线程安全实现,建议使用HashMap代替Hashtable 。 如果需要线程安全的高度并发实现,则建议使用ConcurrentHashMap代替Hashtable 。
不能存储null值作为key和value
初始容量为11 ,加载因子0.75, 每次扩容原容量的2倍+1
public static void main(String[] args) {
HashMap map = new HashMap<>();
map.put(null,null);
}
TreeMap
TreeMap --> TreeSet是由TreeMap的key维护的
底层: 红黑树
特点: 自动根据key做升序排序
去重存储: 如果存储的是java提供的引用类型,java提供比较规则,不用管直接用
如果存储的是自定义提供的引用类型,自己实现比较规则
注意:Map的去重…都是根据键值对的key操作
比较规则:
内部比较器 Comparable
初始容量为11 ,加载因子0.75, 每次扩容原容量的2倍+1
public static void main(String[] args) {
HashMap map = new HashMap<>();
map.put(null,null);
}
TreeMap
TreeMap --> TreeSet是由TreeMap的key维护的
底层: 红黑树
特点: 自动根据key做升序排序
去重存储: 如果存储的是java提供的引用类型,java提供比较规则,不用管直接用
如果存储的是自定义提供的引用类型,自己实现比较规则
注意:Map的去重…都是根据键值对的key操作
比较规则:
内部比较器 Comparable
外部比较器 Comparator