简述
在我看来java中的List、Set、Map三者都是对数据进行操作。
其核心为增、删、查、改(set不能直接更改)。
在此基础上三者各有特点。
List
一、使用: ArrayList、LinkedList、Vector三者基本一致,即方法调用基本相同且三者都是有序的 、可重复的。 其强调顺序。
二、底层实现与安全性:
类 | 底层实现 | 安全性 |
---|---|---|
Vector | 数组 | 安全 |
ArrayList | 数组 | 不安全 |
LinkedList | 双向链表 | 不安全 |
此处安全是指同一时刻只有一个进程可操作该元素。
其中Vector已经过时。
三、速度比较:
参数类型 | 增加元素 | 删除元素 | 修改元素 | 查询元素 |
---|---|---|---|---|
ArrayList | 慢 | 慢 | 快 | 快 |
LinkedList | 快 | 快 | 慢 | 慢 |
Set
一、使用: HashSet、TreeSet两者方法调用基本相同,但是其重复性和排序与List稍有不同。普遍认为其值不能重复,且HashSet无序、TreeSet可设置(详见三)。其强调查找,以及数据的唯一性。
二、底层实现与安全性:
类 | 底层实现 | 安全性 |
---|---|---|
HashSet | 哈希表 (元素为链表的数组,向下存储的方式) | 不安全 |
TreeSet | 红黑树 (特殊二叉树) | 不安全 |
三、排序与重复性问题:
1、HashSet:
重复性: HashSet的重复性取决与 HashCode()与equals() 方法,也就是说我们可以通过重写上述两方法来达到决定元素是否重复的问题。
排序: HashSet的排序是不能保证有序的。对于自己实现的类我们可以通过重写HashCode()来达到重写的目的。1
2、TreeSet: TreeSet的重复性与排序问题取决于其比较器的设置,这里比较器设置的方法我了解的有两种。
a、 实体类实现Comparable接口重写方法 compareTo。
b、 自己实现比较器 comparator 实现compare,然后以参数的形式传递给构造函数。
以上两种方法都是通过其返回值不同来确定元素的顺序。 返回正数表示需要交换位置,负数表示不交换,零表示相等不需要交换(也可以作为多条件判断的依据,即前面的属性相等需进行下一个属性的判断)
Map
一、使用: HashSet、TreeMap两者方法调用基本相同。其中数据以键值对的形式存储(key,value),其中key值不能相同,value可相同。同时key与value都可以为null值。 其强调key与value的配对以及查找。
二、底层实现与安全性:
类 | 底层实现 | 安全 |
---|---|---|
HashMap | Hash表(数组、单链表、红黑树) | 不安全 |
TreeMap | 红黑树 | 不安全 |
三、元素获取:
其元素获取的方法在我看来有三种:
- 将map中的key存储到set集合中,遍历set集合获得value值
for (String key : map.keySet()) {
//可以通过key获得value
String value = map.get(key);
System.out.println("key:"+key +" value:"+value);
}
2. 将key-value组成一个Entry对象,存储到set集合中,遍历set集合即可
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println("key:"+entry.getKey() +" value:"+entry.getValue());
}
3. jdk8的新特性
map.forEach((k,v)->{System.out.println(k+"---"+v);})
补: 对于TreeMap来说它同TreeSet一样是可以指定比较器来决定元素的获取顺序的。
不保证这段话的准确性,这里牵扯到了HashMap里对于哈希地址的计算。我仅仅进行了一丢丢的尝试发现的确可以影响其顺序。这个操作就是讲hash的返回值改为int类型的hashcode。当然了解就行,我是不会这么做的,需要设置读取顺序时TreeSet不香吗。 ↩︎