java集合
java比较器
自然排序Comparable
1.实现Comparable接口。
2.像string,包装类等实现了Comparable接口,重写了compareTo方法,给出了比较两个对象大小的方式,且进行从小到大的排序。
3.重写compareTo方法的原则:
如果当前对象this大于形参对象,则返回正整数,小于返回负整数,相等返回0。
4.大概代码思路如下
public int compareTo(Object o) {
if(o instanceof Goods){
Goods goods = (Goods)o;
if(this.price > goods.price){
return 1;
}else if(this.price < goods.price){
return -1;
}else{
return -this.name.compareTo(goods.name);
}
}
throw new RuntimeException("传入的数据类型不一致!");
}
定制排序Comparator
1.使用Comparator的对象来排序,重写compare方法,比较大小,如果返回正整数,则表示o1大于02,负整数,小于,0,等于。
2.如果只需要创建一个对象,我们可以通过匿名子类的方式来实现。
3.代码如下
Comparator com = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Goods && o2 instanceof Goods) {
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
if (g1.getName().equals(g2.getName())) {
return -Double.compare(g1.getPrice(), g2.getPrice());
} else {
return g1.getName().compareTo(g2.getName());
}
}
throw new RuntimeException("输入的数据类型不一致");
}
};
Collection interface
Iterator
用于遍历集合
Collection coll = new ArrayList();
coll.add(1);
coll.add(2);
Iterator iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
常用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1RXyQk5P-1634885056133)(C:\Users\HUAWEI\AppData\Roaming\Typora\typora-user-images\image-20211022130925290.png)]
List interface
存储有序的,可重复的数据,所在类要重写equals方法。
ArrayList class
一 特点
为List接口的主要实现类,线程不安全的,底层使用数组存储,增删效率低,查找效率高,因为用角标查找。
二 源码分析
1.jdk7的情况下
初始化在底层创建了长度是10的object[]数组,如果添加导致底层数组容量不够,则扩容,默认情况下,扩容为原来容量的1.5倍,同时需要将原有的数组中的数据复制到新的数组中。
2.jdk8的情况下
初始化时并没有创建长度为10的数组,第一次调用add才会创建长度为10的数组,后续扩容操作与jdk7无异。
3.小结
jdk7的对象创建类似于单例的饿汉式,jdk8的对象创建类似于单例的懒汉式,延迟了数组的创建,节省内存。
LinkedList class
1.特点
对于频繁的插入删除操作,使用此类效率比ArrayList高,底层使用双向链表存储,但是查找效率低。
2.源码分析
内部声明了Node类型的first和last属性,默认值为null,node定义体现了双向链表的说法。
Vector class
1.特点
作为List接口的古老实现类,线程安全,因为所有方法被synchornized修饰,底层用数组存储。
2.源码分析
7与8都是创建对象时便定义了长度为10的数组,在扩容方面,默认扩容为原来的两倍。
Set interface
1.无序性,不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,二十根据数据的哈希值决定的。
2.不可重复性,保证添加的元素按照equals判断时,不能返回true,相同元素只能添加一个。
HashSet class
1.特点
线程不安全,可以储存null
2.源码分析
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置,判断数组此位子上是否已经有了元素)。
①若此位置上没有元素,此元素a添加成功。
②若此位置上有了其他元素b,或多个元素,则比较a与b的hash值,若hash值不相同,则添加成功。
③若hash值相同,调用a所在类的equals方法,返回true,添加失败,返回false,添加成功。
在该位置已有元素的情况下,将该索引位置上的数据以链表的方式存储。
jdk7中,将新添元素放入数组,指向原来的元素。
jdk8中,原来的元素不变,指向新添的元素。
底层:数组+链表。
TreeSet class
1.特点
在放入数据后,即会排序,所以我们放入的数据,必须是实现了排序的类。
两种方式,自然排序和定制排序。
2.实现
如果是自然排序,则空参构造器即可。
如果是定制排序,需要将Comparator的对象放入构造器。
LinkedHashSet
作为HashSet的子类,遍历时可以按照添加顺序遍历。(因为在添加数据的时候,每个数据还维护了两个引用,,记录此数据的前一个和后一个数据)。
对于频繁的遍历操作,LinkedHashSet效率高于HashSet。
map interface
双列数据,存储key value对的数据。
key是无序的不可重复的,使用Set存储的key,key所在的类要重写equals和hashcode方法。
value是无序的,可重复的,使用Collection存储value,需要重写equals方法
一个键值对,key value 构成了一个Entry或者Note对象。
entry也是无序的不可重复的,用Set存储。
常用方法
* 添加:put(Object key,Object value)
* 删除:remove(Object key)
* 修改:put(Object key,Object value)
* 查询:get(Object key)
* 长度:size()
* 遍历:keySet() / values() / entrySet()
HashMap class
1.特点
作为Map的主要实现类,线程不安全的,效率高,可以存储null的key和value。
2.HashMap底层典型属性的属性的说明:
DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
threshold:扩容的临界值,=容量*填充因子:16 * 0.75 => 12
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64
3.底层源码分析
jdk7
① 在实例化后,底层创建了一个长度是16的一维数组Entry[] table。
②与set的添加形式相同
③若超过临界值,扩容,默认的扩容方式为容量的两倍,并将原来的数据复制过来。
jdk8
①初始化时没有创建数组,在添加时创建长度为16的Node[] 数组。
②底层结构
jdk7 数组+链表
jdk8 数组+链表+红黑树
③链表的存储差别关于7和8,与set相同
④当数组某一个索引的元素以链表形式存在的数据个数》8,且当前数组的长度为《64,此时此索引位置上的所有数据改为红黑树存储。
TreeMap class
与TreeSet大致相同思路
Hashtable class
作为古老的实现类,线程安全,不能存储null的key和value
LinkedHashMap class
保证在遍历map时,可以按照添加的顺序实现遍历
原有,在原有的HashMap的底层结构基础上,添加了一对指针,指向前一个和后一个元素,对于频繁的遍历操作,此类执行效率高于HashMap。
|