本篇文章据本人权威判断不太行,推荐阅读https://blog.csdn.net/Sampson_S/article/details/109149575
java集合框架
概念:对象的容器,定义了多个对象进行操作的常用方法。
集合和数组的区别
- 数组长度固定,集合长度不固定
- 数组可以存基本类型和引用类型,集合只能引用类型
Collection体系集合
- Interface:
- Collection: 体系的根接口,代表一组对象,成为“集合”。
- List: 有序、有下标、元素可重复。
- Set: 无序、无下标
Collection
无下标
Collection的iterator()方法返回一个Iterator迭代器
Iterator iterator()
返回此集合中的元素的迭代器。
在迭代器遍历过程中不能使用Collection的删除方法,否则会导致并发修改异常。应该使用Iterator.remove()方法。
List
特点:有序、有下标、元素可以重复
相比Collection 某些方法多了index,有了关于下标操作的方法。
ArrayList
数组结构实现,查询快,增删慢
JDK1.2版本,运行效率高,线程不安全
private static final int DEFAULT_CAPACITY = 10;//默认空间10、
transient Object[] elementData; // 存放数据的位置
private int size;//数组大小
new ArrayList();//size=0大小为0,capacity=0容量为0
//当添加object到ArrayList的时候调用add();
add()->ensureCapacityInternal(size+1)->grow(minCapacity);
ArrayList初始容量0,大小0,当添加一个元素的时候增加至DEFAULT_CAPACITY=10。
当扩充容量小于本身1.5倍的时候,容量扩容至本身的1.5倍,大于1.5倍的时候扩容至指定容量。
Vector
Vector集合是对ArrayList集合线程安全的实现,它们两者在方法的实现上没有什么太大的区别,最大的区别就是,Vector在方法前面加上了synchronized关键字,用于保证线程安全。
Vector存在的问题:
1、它的add()和get()方法都能够获取当前Vector对象的对象锁,但是有可能会发生读读互斥。
2、当threadA在1下标处添加一个元素,threadB在2下标处修改一个元素时,同样有可能会发生互斥现象。
数组结构实现,查询快,增删慢
JDK1.2版本,运行效率低,线程安全
自动扩容,若构造对象有指定容量capacityIncrement,则在传入扩容量小于本身capacityIncrement两倍的前提下,扩容两倍,构造的时候没有指定的时候扩容之前就容量的两倍
LinkedList
链表结构实现,增删快,查询慢。
双向链表
Set
特点:无序,无下标,元素不可以重复
方法:全部继承自Collection中的方法
HashSet源码层是通过HashMap的key实现的,value统一为Object对象
TreeSet源码层是通过TreeMap的key实现,value统一为Object对象
HashSet
储存结构:数组+链表,jdk8之后为数组+链表+红黑树
储存过程:
- 根据hashcode计算保存位置,如果该位置为空,则直接保存
- 如果不为空,执行equals(),如果相同则认为重复,不同则形成链表
编码注意:重写hashCode()方法,重写equals()方法
hashCode中使用31的原因:
- 31是一个质数,减少散列的冲突
- 提高执行效率,31*i=(i<<5)-i
TreeSet
储存结构:红黑树
基于排列顺序实现元素不重复
实现了SortedSet接口,对集合元素自动排序
- 元素对象必须实现Comparable接口,指定排序规则,通过CompareTo方法确定是否为重复元素
- 或者构造TreeSet的时候传入一个比较器Comparator
TreeSet<String> set = new TreeSet<>(new Comparator<String>(){
@Override
public int Compare(String s1,String s2){
int n = s1.lenth-s2.lenth;
int n2 = s1.compareTo(s2);
reture n==0?n2:n;
}
})
Map
map接口特点:
- 用于储存任意键值对(key-value)
- 键:无序,无下标,不允许重复
- 值:无序,无下标,允许重复
HashMap
JDK1.2版本,线程不安全,运行效率快;允许使用null作为key或者value
储存结构:哈希表(数组+链表+红黑树)
初始容量16,默认加载因子0.75(大小超过容量的75%的时候开始自动扩容)
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//0.75加载因子
static final int TREEIFY_THRESHOLD = 8;
static final int MIN_TREEIFY_CAPACITY = 64;
//当某位置链表大于8,且数组长度大于64,则大于8的地方变为红黑树
static final int UNTREEIFY_THRESHOLD = 6;
//当某位置红黑树节点数小于6时变为链表
//蜕变阈值为什么不设置为8?
//防止频繁链和树的变换
transient Node<K,V>[] table;
//HashMap存值
HashTable
JDK1.0,线程安全,运行效率慢,不允许null作为key或者value
初始容量11 加载因子0.75
Properties
HashTable的子类,要求key和value都是String。通常用于配置文件的读取。
TreeMap
实现了SortedMap接口,可以对Key排序
储存结构:红黑树
Collections工具集
数组转集合 Arrays.asList()
返回的List不可增删,因为返回的List是Arrays的内部私有类。
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
该内部类没有重写抽象类的增删方法
泛型
java泛型是JDK1.5中引入的一个新特性
泛型本质就是参数化类型,把类型作为参数传递
常见形式有泛型类,泛型接口,泛型方法<T,…>T称为占位符,表示一种引用类型
意义:
- 提高代码的重用
- 防止类型转换异常,提高代码的安全性
public class MyGeneric<E> {
public E e;
public void show(E e) {
System.out.println(e);
}
public E get() {
return e;
}
}
public static void main(String[] args) {
MyGeneric<String> generic = new MyGeneric<>();
generic.e = "hello";
System.out.println(generic.get());
}
注意
- 泛型只能使用引用类型
- 不同泛型对象之间不能相互赋值