集合(下)

7 Set 接口

Set 接口表示一个唯一、无序的容器(和添加顺序无关)。

7.1 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 }

7.2 Set 的遍历

 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 }

8 HashSet

HashSet 是 Set 接口的实现类,底层数据结构是哈希表。HashSet 是线程不安全的(不保证同步)。优点:添加、删除、查询效率高;缺点:无序

8.1 添加自定义对象

如果向 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 }

9 LinkedHashSet

LinkedHashSet是Set接口的实现类,底层数据结构哈希表+链表。哈希表用于散列元素;链表用于维持添加顺序。如果要添加自定义对象元素,也需要重写 hashCode 和 equals 方法。

10 TreeSet

TreeSet 是Set接口的实现类,底层数据结构是二叉树。TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现出自然顺序。

10.1 工作原理

添加一个新元素 t 的存储的步骤:

  1. 如果集合无元素,t 直接加入;如果集合有元素,t 和根节点比较;
  2. 如果 t 小于根节点;把 t 放到根节点的左子树上;重复1-3步骤
  3. t 大于根节点;把 t 放到根节点的右子树上;重复1-3步骤

输出时按照一定的规则:左子树->根节点->右子树

向TreeSet中添加元素时,一定要提供比较策略,否则会出现 ClassCastException。

10.2 内部比较器

当一个自定义对象实现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 即可实现升序排列。

10.3 外部比较器

当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。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 }

11 Map 接口

Map接口称为键值对集合或者映射集合,其中的元素(entry)是以键值对(key-value)的形式存在。Map 容器接口中提供了增、删、改、查的方式对集合进行操作。Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value。

11.1 Map 常用方法

 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 }

11.2 Map 的遍历

  • 通过keySet() 返回map中键的set集合。
 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 }
  • Map 中以键值对作为元素,键值对在map中称为entry,entrySet() 返回键值对的set集合,通过此集合遍历。
 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 }

12 HashMap

HashMap 是 Map 的实现类,key 以 HashSet 存储。HashMap 线程不安全,jdk1.2;Hashtable 是 HashMap 的线程安全版本,jdk1.0。向HashMap中存储元素时,key一定要实现 hashCode 和 equals。

13 LinkedHashMap

LinkedHashMap 是 Map 接口的实现类,key 以 LinkedHashSet 存储。哈希表散列key,链表维持key的添加顺序。

14 TreeMap

TreeMap 是 Map 的实现类,key 以 TreeSet 存储。key 如 TreeSet 一样要具有比较器。

15 总结

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python的类和对象

    面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。理解面向对象编程有助于你像程序员那样看世...

    stormwen
  • Python的类和方法——成员可见性

    使用装饰器@classmethod。第一参数必须是当前类对象,该参数名一般约定为「cls」,当然cls也可以换成其他名字,通过它来传递类的属性和方法(不能传实例...

    stormwen
  • Python的类的继承

    继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来类的情况下对这些类进行扩展。

    stormwen
  • Encoding and Decoding Custom Types

    许多编程任务涉及通过网络连接发送数据,将数据保存到磁盘或将数据提交到API和服务。 这些任务通常要求在传输数据时将数据编码和解码为中间格式。

    SheltonWan
  • 正则表达式(三)

    这两天在读刻意练习,这本书写的很好,里面有一段是这样写的:“我深深地困在,当前的处境中。四面高墙,定义了我的空间格局。我就在这里,生活了很多年,而且可能继续...

    stormwen
  • 第三章、Go-内建容器

    zhang_derek
  • Python练手题目(七)

    编写一个函数,该函数将返回在输入字符串中出现多次(不同的不区分大小写的)字母字符和数字的计数。可以假定输入字符串仅包含字母(大写和小写)和数字。

    stormwen
  • Python的高级语法与用法

    Python是一种易于学习又功能强大的编程语言。它不仅有简单有效的面向对象编程,还有高效的高级数据结构,就让我们一起来学习这部分的内容吧。

    stormwen
  • 400多人刷过的一道Python题目

    最近写的文章会偏向于Python实战一些,大家不要看着刷题,心里就有抵触了,其实刷题一直是学习的一个必要途径。你想想高中时候,如果你光听听课,学学理论就行的话,...

    stormwen
  • Python变量和运算符

    变量名首字符不能是数字,变量名只能用字母、数字、下划线命名,系统保留关键字不能用在变量名中。

    stormwen

扫码关注云+社区

领取腾讯云代金券