Set 接口表示一个唯一、无序的容器(和添加顺序无关)。
1 public static void main(String[] args) {
2 /**
3 * 增:add/addAll
4 * 删:clear/remove/removeAll/retainAll
5 * 改:
6 * 查:contains/containsAll
7 * 遍历:iterator
8 * 其他:size/isEmpty
9 */
10
11 Set<Integer> set = new HashSet<Integer>();
12 // [1]添加
13 // 无序
14 set.add(10);
15 set.add(3);
16 set.add(20);
17 set.add(0);
18 // 不能添加重复元素
19 boolean r = set.add(1);
20 System.out.println(set);
21
22 // 【2】删除
23 // set.remove(1);
24 // set.clear();
25 // System.out.println(set);
26
27 // 【3】查看是否包含
28 System.out.println(set.contains(1));
29
30 // 【4】其他
31 System.out.println(set.size());
32 System.out.println(set.isEmpty());
33 }
1 public static void main(String[] args) {
2
3 Set<String> set = new HashSet<String>();
4 set.add("banana");
5 set.add("apple");
6 set.add("coco");
7
8 // 快速遍历
9 for (String item : set) {
10 System.out.println(item);
11 }
12
13 // 迭代器
14 Iterator<String> it = set.iterator();
15 while(it.hasNext()) {
16 String item = it.next();
17 System.out.println(item);
18 }
19 }
HashSet 是 Set 接口的实现类,底层数据结构是哈希表。HashSet 是线程不安全的(不保证同步)。优点:添加、删除、查询效率高;缺点:无序
如果向 HashSet 中存储元素时,元素一定要实现hashCode方法和equals方法。
1 public class Student {
2 private String id;
3 private String name;
4 private int age;
5
6 @Override
7 public int hashCode() {
8 final int prime = 31;
9 int result = 1;
10 result = prime * result + age;
11 result = prime * result + ((id == null) ? 0 : id.hashCode());
12 result = prime * result + ((name == null) ? 0 : name.hashCode());
13 return result;
14 }//当属性相同时,两个对象的 hashcode 相同,判断两个对象相等的必要不充分条件
15
16 @Override
17 public boolean equals(Object obj) {
18 if (this == obj)
19 return true;
20 if (obj == null)
21 return false;
22 if (getClass() != obj.getClass())
23 return false;
24 Student other = (Student) obj;
25 if (age != other.age)
26 return false;
27 if (id == null) {
28 if (other.id != null)
29 return false;
30 } else if (!id.equals(other.id))
31 return false;
32 if (name == null) {
33 if (other.name != null)
34 return false;
35 } else if (!name.equals(other.name))
36 return false;
37 return true;
38 }//两个对象相等的充分必要条件
39
40 @Override
41 public String toString() {
42 return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
43 }
44
45 }
LinkedHashSet是Set接口的实现类,底层数据结构哈希表+链表。哈希表用于散列元素;链表用于维持添加顺序。如果要添加自定义对象元素,也需要重写 hashCode 和 equals 方法。
TreeSet 是Set接口的实现类,底层数据结构是二叉树。TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现出自然顺序。
添加一个新元素 t 的存储的步骤:
输出时按照一定的规则:左子树->根节点->右子树
向TreeSet中添加元素时,一定要提供比较策略,否则会出现 ClassCastException。
当一个自定义对象实现Comparable并实现compareTo方法时,通过指定具体的比较策略,此时称为内部比较器。
1 public class Student implements Comparable<Student>{
2 private String id;
3 private String name;
4 private int age;
5
6 @Override
7 public String toString() {
8 return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
9 }
10
11 @Override
12 public int compareTo(Student o) {
13 if(this.getAge()<o.getAge()) {
14 return -1;
15 }else if(this.getAge() == o.getAge()) {
16 return 0;
17 }else {
18 return 1;
19 }
20 }
21
22 }
默认的比较器是按升序排列,所以只要重写的 compareTo 方法也是参数较大时返回 -1 即可实现升序排列。
当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。TreeSet 接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现 Compa-rator 接口。Comparator 位于java.util包中,定义了compare (o1,o2) 用于提供外部比较策略。推荐使用匿名内部类方法实现。
1 public static void main(String[] args) {
2
3 TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {
4
5 @Override
6 public int compare(String o1, String o2) {
7 return o1.length() - o2.length();
8 }
9
10 });//比较规则是字符串长度的升序
11
12 set2.add("banana");
13 set2.add("coco");
14 set2.add("apple");
15
16 set2.add("apple");
17 System.out.println(set2);
18
19 }
Map接口称为键值对集合或者映射集合,其中的元素(entry)是以键值对(key-value)的形式存在。Map 容器接口中提供了增、删、改、查的方式对集合进行操作。Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value。
1 public static void main(String[] args) {
2
3 /**
4 * 增:put/putAll
5 * 删:clear/remove
6 * 改:put
7 * 查:get/containsKey/containsValue
8 * 其他:isEmpty/size
9 */
10
11 Map<String, String> map = new HashMap<String,String>();
12
13 // 【1】put
14 map.put("A", "apple");
15 map.put("B", "banana");
16 map.put("C", "coco");
17
18 // 【2】删除
19 // map.clear();
20 // smap.remove("A");
21
22 // 【3】修改
23 //map.put("A", "apple x");
24
25 // 【4】查看
26 String val = map.get("A");
27 System.out.println(map.containsKey("D"));
28
29
30 System.out.println(map);
31 }
1 public static void main(String[] args) {
2
3 Map<String, String> map = new HashMap<String,String>();
4
5 map.put("B", "banana");
6 map.put("A", "apple");
7 map.put("C", "coco");
8 // map无序
9 // 可以根据key的自然顺序 让map有序 => 一般用string作为key
10 System.out.println(map);
11
12
13 // 遍历
14 Set<String> keys = map.keySet();
15 for (String key : keys) {
16 System.out.println(key+"=>"+map.get(key));
17 }
18
19 Iterator<String> it = keys.iterator();
20 while(it.hasNext()) {
21 String key = it.next();
22 System.out.println(key+"=>"+map.get(key));
23 }
24 }
1 public static void main(String[] args) {
2
3 Map<String, String> map = new HashMap<String,String>();
4
5 map.put("B", "banana");
6 map.put("A", "apple");
7 map.put("C", "coco");
8 // map无序
9 // 可以根据key的自然顺序 让map有序 => 一般用string作为key
10 System.out.println(map);
11
12 // entrySet
13 Set<Entry<String, String>> entrySet = map.entrySet();
14 for (Entry<String, String> entry : entrySet) {
15 System.out.println(entry.getKey()+"=>"+entry.getValue());
16 }
17
18 Iterator<Entry<String, String>> it2 = entrySet.iterator();
19 while(it2.hasNext()) {
20 Entry<String, String> entry = it2.next();
21 System.out.println(entry.getKey()+"=>"+entry.getValue());
22 }
23 }
HashMap 是 Map 的实现类,key 以 HashSet 存储。HashMap 线程不安全,jdk1.2;Hashtable 是 HashMap 的线程安全版本,jdk1.0。向HashMap中存储元素时,key一定要实现 hashCode 和 equals。
LinkedHashMap 是 Map 接口的实现类,key 以 LinkedHashSet 存储。哈希表散列key,链表维持key的添加顺序。
TreeMap 是 Map 的实现类,key 以 TreeSet 存储。key 如 TreeSet 一样要具有比较器。