Appearance
记录一下集合相关的概念,对于 Java 集合基础概念的一个补充
1、什么是 fail-fast机制,讲述一下他和 fail-safe 的异同。
错误检查机制
- 快速失败 fail-fast
- 当方法检测到对象的并发修改,但不允许这种修改时就抛出该异常
- fail-safe 机制
- fail-safe 任何对集合结构的修改都会在一个复制的集合上进行,因此不会抛出ConcurrentModificationException
fail-fast 解决方法
- 方案一:在遍历过程中所有涉及到改变modCount 值的地方全部加上synchronized 或者直接使用 Collection synchronizedList,这样就可以解决问题,但是不推荐,因为增删造成的同步锁可能会阻塞遍历操作。
- 方案二:使用CopyOnWriteArrayList 替换 ArrayLIst,推荐使用该方案(即fail-safe)。
fail-fast和 fail-safe 的区别
| Fail Fast Iterator | Fail Safe Iterator | |
|---|---|---|
| Throw ConcurrentModification Exception | Yes | No |
| Clone object | No | Yes |
| Memory Overhead | No | Yes |
| Examples | HashMap,Vector,ArrayList,HashSet | CopyOnWriteArrayList, ConcurrentHashMap |
2、通过实现 Comparable 或者 Comparator 接口来进行排序
一种情况是集合类本身自带排序功能,如前面说过的TreeSet、SortedSet、SortedMap等,
另一种就是本身不带排序功能,我们通过为需要排序的类实现 Comparable 或者 Comparator 接口来实现。
先来看两个例子,一个是实现Comparable的,一个是实现 Comparator 的
(1)实现Comparable的:
package com.xtfggef.list.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("unchecked")
public class ComparableTest {
public static void main(String[] args) {
List<User> users = new ArrayList();
users.add(new User("egg", 23));
users.add(new User("niu", 22));
users.add(new User("qing", 28));
Collections.sort(users);
for (User user : users) {
System.out.println(user.getName() + " " + user.getAge());
}
}
}
@SuppressWarnings("unchecked")
class User implements Comparable {
private String name;
private int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Object o) {
return this.age - ((User) o).getAge();
}
}(2)下面是实现Comparator接口的:
package com.xtfggef.comparator.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparatorTest {
public static void main(String[] args) {
List<User> users = new ArrayList();
users.add(new User("egg", 21));
users.add(new User("niu", 22));
users.add(new User("gg", 29));
UserComparator comparator = new UserComparator();
Collections.sort(users, comparator);
for (User user : users) {
System.out.println(user.getUsername() + " " + user.getAge());
}
}
}
class User {
private String username;
private int age;
public User(String username, int age) {
super();
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class UserComparator implements Comparator<User> {
@Override
public int compare(User user1, User user2) {
int age1 = user1.getAge();
int age2 = user2.getAge();
if (age1 < age2) {
return 1;
}
return 0;
}
}👆 上面这种 Comparator 实现这个接口的时候, 👉 Comparator是一个泛型接口,所以在实现Comparator接口时,类的泛型类型需要指定具体类型,以避免类型擦除带来的问题。
通过上面的这两个小例子,我们可以看出,Comparator和Comparable用于不同的场景,实现对对象的比较从而进行排序。
总结为:
相同点: 二者都可以实现对象的排序,不论用 Arrays的方法还是用 Collections的sort()方法。
不同点:
(1)实现Comparable接口的类,似乎是预先知道该类将要进行排序,需要排序的类实现Comparable接口,是一种“静态绑定排序”。
(2)实现Comparator的类不需要,设计者无需事先为需要排序的类实现任何接口。
(3)Comparator接口里有两个抽象方法compare()和equals(),而Comparable接口里只有一个方法:compareTo()。
(4)Comparator接口无需改变排序类的内部,也就是说实现算法和数据分离,是一个良好的设计,是一种“动态绑定排序”。
(5)Comparator接口可以使用多种排序标准,比如升序、降序等。