Java集合框架小结
一、for-each与迭代器比较
关于for-each
- 对于普通数组,底层使用for循环+索引获取元素值;
- 对于集合,底层采用的是iterator.
- 一般地,直接使用for-each迭代数组和集合即可
关于Iterator
在边迭代集合边删除其中元素时,如直接在for-each循环中删除元素,会报错!
错误原因:
使用迭代器的时候,会在当前线程A 创建一个线程B,A线程执行迭代操作,B线程执行删除操作,B线程每次会去检查是否与A线程元素匹配,如果不匹配则报错!-
解决方案:
- 使用for循环倒序迭代并删除其中元素;
- 使用Iterator的remove方法
二、ArrayList与Vector
- 底层操作的都是Object数组;
- Vector从jdk1.0就有了,而ArrayList是从jdk1.2引入的;
- Vector所有的方法都使用了synchronized修饰符,是线程安全的;
- ArrayList 所有的方法都没有使用synchronized修饰符,线程不安全但是性能较高.
即使以后在多线程环境下,我们也不使用Vector类:
ArrayList list = Collections.synchronizedList(new ArrayList(…));
三、ArrayList与LinkedList
-
共同点
- 都实现了List接口;
- 允许元素重复;
- 记录元素的先后添加顺序;
- 都是线程不安全的 .
-
区别
- ArrayList顾名思义,底层采用的是数组结构算法;
- LinkedList采用的是链表结构算法.
-
性能比较
- 数组结构算法: 插入和删除操作速度低,查询和更改较快.
- 链表结构算法: 插入和删除操作速度快,查询和更改较慢.
四、HashSet中是如何判断两个对象是否相等?
-
判断方法:
- 两个对象的equals比较相等. 返回true,则说明是相同对象.
- 两个对象的hashCode方法返回值相等.
二者:缺一不可.
-
往HashSet对象中存放元素时,判断流程:
- 先会判断该对象和集合对象中的hashCode值:
- 不等: 直接把该新的对象存储到hashCode指定的位置.
- 相等: 再继续判断新对象和集合对象中的equals做比较.
- hashCode相同,equals为true: 则视为是同一个对象,则不保存在哈希表中.
- hashCode相同,equals为false:非常麻烦,存储在之前对象同槽为的链表上(拒绝,操作比较麻烦).
-
因此:
- 如果o1.equals(o2),那么o1.hashCode() == o2.hashCode()总是为true的。
- 如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)会为true。
五、Comparable和Comparator接口是什么?
如果我们想使用Array或Collection的排序方法时,需要在自定义类里实现Java提供Comparable接口。Comparable接口有compareTo(T OBJ)方法,它被排序方法所使用。我们应该重写这个方法,如果“this”对象比传递的对象参数更小、相等或更大时,它返回一个负整数、0或正整数。但是,在大多数实际情况下,我们想根据不同参数进行排序。比如,作为一个CEO,我想对雇员基于薪资进行排序,一个HR想基于年龄对他们进行排序。这就是我们需要使用Comparator接口的情景,因为Comparable.compareTo(Object o)方法实现只能基于一个字段进行排序,我们不能根据对象排序的需要选择字段。Comparator接口的compare(Object o1, Object o2)方法的实现需要传递两个对象参数,若第一个参数比第二个小,返回负整数;若第一个等于第二个,返回0;若第一个比第二个大,返回正整数。
六、TreeSet中元素排序
因此,要求TreeSet集合中元素得实现java.util.Comparable接口.
覆盖 public int compareTo(Object o)方法,在该方法中编写比较规则.
在该方法中,比较当前对象(this)和参数对象o做比较(严格上说比较的是对象中的数据,比如按照对象的年龄排序).
this > o: 返回正整数. 1
this < o: 返回负整数. -1
this == o: 返回0. 此时认为两个对象为同一个对象.
定制排序(从大到小,按照名字的长短来排序):
在TreeSet构造器中传递java.lang.Comparator对象.并覆盖
public int compare(Object o1, Object o2)再编写比较规则.对于TreeSet集合来说,要么使用自然排序,要么使用定制排序.
判断两个对象是否相等的规则:
自然排序: compareTo方法返回0;
定制排序: compare方法返回0;