【原】Java学习笔记029 - 映射

 1 package cn.temptation;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 public class Sample01 {
 7     public static void main(String[] args) {
 8         /*
 9          * Collection接口及其子接口、实现类 等            称为   单列集合
10          * Map接口及其子接口、实现类等                称为   双列集合
11          * 
12          * 接口 Map<K,V>:映射,将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。 
13          * 
14          * Map(映射)由两部分组成:键(Key)和值(Value)
15          * 
16          * 特点:
17          * 1、一个映射不能包含重复的键
18          * 2、每个键最多只能映射到一个值
19          * 3、映射中的键值对是无序的
20          * 
21          * 理解Map(映射):
22          * 联想地图,能唯一确定地点使用的是坐标,地图上没有两个相同的坐标
23          * 但是地图上可以有相同的地名,比如不同省份下的区县可能名字相同,但是它们的坐标是不同的
24          * 地图上的坐标就是键,地名就是值
25          * 
26          * Map<K,V>接口的常用成员方法:
27          * 1、添加功能
28          * V put(K key, V value) :将指定的值与此映射中的指定键关联(可选操作)。 
29          * 返回:以前与 key 关联的值,如果没有针对 key 的映射关系,则返回 null。(如果该实现支持 null 值,则返回 null 也可能表示此映射以前将 null 与 key 关联)。
30          * 
31          * 2、删除功能
32          * void clear() :从此映射中移除所有映射关系(可选操作)。
33          * V remove(Object key) :如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。  
34          * 
35          * 3、判断功能
36          * boolean containsKey(Object key) :如果此映射包含指定键的映射关系,则返回 true。 
37          * boolean containsValue(Object value) :如果此映射将一个或多个键映射到指定值,则返回 true。 
38          * 
39          * boolean isEmpty() :如果此映射未包含键-值映射关系,则返回 true。
40          * 
41          * 4、长度功能
42          * int size() :返回此映射中的键-值映射关系数。 
43          * 
44          */
45         Map<String, String> map = new HashMap<>();
46         
47         System.out.println("map:" + map);            // map:{}
48         
49         // 1、添加功能
50         // 如果把Map的键值对理解为夫妻的话,那么其put方法可以认为是返回伴侣的前任
51 //        System.out.println("map`s put:" + map.put("高祖", "杨开慧"));        // map`s put:null
52 //        System.out.println("map`s put:" + map.put("高祖", "贺子珍"));        // map`s put:杨开慧
53 //        System.out.println("map`s put:" + map.put("高祖", "江青"));        // map`s put:贺子珍
54         
55         map.put("秦皇", "嬴政");
56         map.put("汉武", "刘彻");
57         map.put("唐宗", "李世民");
58         map.put("宋祖", "赵匡胤");
59         map.put("一代天骄", "成吉思汗");
60         // 键值对映射关系中,键相同的,通过put添加后显示的是最后的那个键值对或者说是最新的那个键值对
61         map.put("一代天骄", "蒋中正");
62         
63         System.out.println("map:" + map);        // map:{汉武=刘彻, 宋祖=赵匡胤, 一代天骄=蒋中正, 唐宗=李世民, 秦皇=嬴政}
64         
65         System.out.println("----------------------------------------------------");
66         
67         // 2、删除功能
68 //        map.clear();
69 //        System.out.println("map:" + map);        // map:{}
70         
71         map.remove("唐宗");
72         System.out.println("map:" + map);        // map:{汉武=刘彻, 宋祖=赵匡胤, 一代天骄=蒋中正, 秦皇=嬴政}
73         
74         System.out.println("map`s remove:" + map.remove("宋祖"));        // map`s remove:赵匡胤
75         System.out.println("map:" + map);        // map:{汉武=刘彻, 一代天骄=蒋中正, 秦皇=嬴政}
76         
77         System.out.println("map`s remove:" + map.remove("西楚霸王"));    // map`s remove:null
78         
79         System.out.println("----------------------------------------------------");
80         
81         // 3、判断功能
82         System.out.println("map`s containsKey:" + map.containsKey("秦皇"));        // map`s containsKey:true
83         System.out.println("map`s containsKey:" + map.containsKey("西楚霸王"));    // map`s containsKey:false
84         
85         System.out.println("map`s containsValue:" + map.containsValue("刘彻"));    // map`s containsValue:true
86         System.out.println("map`s containsValue:" + map.containsValue("刘秀"));    // map`s containsValue:false
87         
88         map.clear();
89         System.out.println("map`s isEmpty:" + map.isEmpty());                    // map`s isEmpty:true
90         
91         // 4、长度功能
92         System.out.println("map`s size:" + map.size());                            // map`s size:0
93     }
94 }
 1 package cn.temptation;
 2 
 3 import java.util.Collection;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 import java.util.Set;
 7 
 8 public class Sample02 {
 9     public static void main(String[] args) {
10         /*
11          * Map<K, V>接口的常用成员方法:
12          * 1、获取功能
13          * V get(Object key) :返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
14          * Set<K> keySet() :返回此映射中包含的键的 Set 视图。
15          * Collection<V> values() :返回此映射中包含的值的 Collection 视图。   
16          */
17         Map<String, String> map = new HashMap<>();
18         
19         map.put("休斯敦", "火箭");
20         map.put("金州", "勇士");
21         map.put("洛杉矶", "湖人");
22         
23         System.out.println(map.get("休斯敦"));        // 火箭
24         System.out.println(map.get("金州"));            // 勇士
25         System.out.println(map.get("洛杉矶"));        // 湖人
26         
27         System.out.println("-------------------------------");
28         
29         // key不能重复
30         // 键值对映射关系中,键相同的,通过put添加后显示的是最后的那个键值对或者说是最新的那个键值对
31         map.put("西雅图", "超音速");
32         map.put("西雅图", "不眠夜");
33         
34         Set<String> set = map.keySet();
35         
36         for (String item : set) {
37             System.out.println(item);
38         }
39         
40         System.out.println("-------------------------------");
41         
42         // value可以重复
43         map.put("夏洛特", "黄蜂");
44         map.put("新奥尔良", "黄蜂");
45         
46         Collection<String> collection = map.values();
47         
48         for (String item : collection) {
49             System.out.println(item);
50         }
51         
52         // 注意:取出的值的顺序 和 放入映射的顺序是不一致的,但是取出的值的顺序 和 取出的键的顺序一致
53     }
54 }
 1 package cn.temptation;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 import java.util.Set;
 7 
 8 public class Sample03 {
 9     public static void main(String[] args) {
10         /*
11          * Map<K, V>接口的常用成员方法:
12          * Set<Map.Entry<K,V>> entrySet() :返回此映射中包含的映射关系的 Set 视图。 
13          * 
14          * 接口 Map.Entry<K,V>:映射项(键-值对)。
15          * 
16          * Map.Entry<K,V>接口的常用成员方法:
17          * 1、K getKey() :返回与此项对应的键。 
18          * 2、V getValue() :返回与此项对应的值。 
19          */
20         Map<String, String> map = new HashMap<>();
21         
22         map.put("德玛西亚之力", "盖伦");
23         map.put("德邦总管", "赵信");
24         map.put("无极剑圣", "易大师");
25         
26         // 遍历Map
27         
28         // 方法1、通过Map接口的keySet方法、get方法
29         Set<String> keySet = map.keySet();
30         for (String key : keySet) {
31             String value = map.get(key);
32             System.out.println("key:" + key + " <-----> " + "value:" + value);
33         }
34         
35         System.out.println("-------------------------------------");
36         
37         // 方法2、通过Map接口的entrySet方法、Entry接口的getKey方法、getValue方法(常用写法)
38         Set<Entry<String,String>> set = map.entrySet();
39         for (Entry<String, String> entry : set) {
40             String key = entry.getKey();
41             String value = entry.getValue();
42             System.out.println("key:" + key + " <-----> " + "value:" + value);
43         }
44     }
45 }
 1 package cn.temptation;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 
 7 public class Sample04 {
 8     public static void main(String[] args) {
 9         /*
10          * 类 HashMap<K,V>:基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
11          */
12         Map<String, String> map = new HashMap<>();
13         
14         map.put("中国", "北京");
15         map.put("美国", "华盛顿");
16         map.put(null, null);
17         
18         // 遍历
19         for (Entry<String, String> entry : map.entrySet()) {
20             String key = entry.getKey();
21             String value = entry.getValue();
22             System.out.println("key:" + key + " <-----> " + "value:" + value);
23         }
24     }
25 }
 1 package cn.temptation;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 
 7 public class Sample05 {
 8     public static void main(String[] args) {
 9         // 需求:在map中存储学生信息(姓名和年龄)及学号,并进行遍历(以学号为key,以学生信息为value)
10         Map<String, Student> map = new HashMap<>();
11         
12         // Map中key这个字符串类型设为学号,通过学号确定唯一性,学生信息作为值
13         map.put("9526", new Student("张三", 20));
14         map.put("9527", new Student("李四", 18));
15         map.put("9528", new Student("王五", 22));
16         // 因为key相同,所以覆盖了前面添加进去的Student对象
17         map.put("9526", new Student("赵六", 16));
18         
19         System.out.println("map:" + map);
20         
21         // 遍历映射
22         for (Entry<String, Student> entry : map.entrySet()) {
23             String id = entry.getKey();
24             Student temp = entry.getValue();
25             System.out.println("学号为:" + id + "," + temp.toString());
26         }
27     }
28 }
  1 package cn.temptation;
  2 
  3 import java.util.Collection;
  4 import java.util.HashMap;
  5 import java.util.Map;
  6 import java.util.Set;
  7 import java.util.Map.Entry;
  8 
  9 public class Sample06 {
 10     // 成员变量
 11     private static Map<Student, String> map = new HashMap<>();
 12     
 13     public static void main(String[] args) {
 14         // 需求:在map中存储学生信息(姓名和年龄)及学号,并进行遍历(以学生信息为key,以学号为value)
 15         // 问题1:如果我们知道这两个学生对象其实指的是同一个人,该如何处理?
 16         // 答:这样学号就不是判断学生的唯一性的标准,而是学生信息是判定学生唯一的依据
 17         
 18         // 问题2:添加学生信息不同的对象,但是学号相同,也加入到map对象中,想避免学号的重复,该如何处理?
 19         // 答:考虑制作自动学号的生成方法,并且制作学生信息判断去重的方法
 20         
 21         // 因为map中的数据不同的成员方法都要使用,所以考虑提取出去作为成员变量
 22 //        Map<Student, String> map = new HashMap<>();
 23         
 24         // Map中key这个字符串类型设为学号,通过学号确定唯一性,学生信息作为值
 25 //        map.put(new Student("张三", 20), "9526");
 26 //        map.put(new Student("李四", 18), "9527");
 27 //        map.put(new Student("王五", 22), "9528");
 28 //        map.put(new Student("张三", 20), "9520");        // 重写Studengt对象的hashCode方法和equals后,就不会出现两个张三 20岁的学生对象了
 29 //        map.put(new Student("赵六", 16), "9527");
 30         
 31         Student student1 = new Student("张三", 20);
 32         if (checkStudent(student1)) {
 33             map.put(student1, getCurrentID());
 34         }
 35         
 36         Student student2 = new Student("李四", 18);
 37         if (checkStudent(student2)) {
 38             map.put(student2, getCurrentID());
 39         }
 40         
 41         Student student3 = new Student("王五", 2);
 42         if (checkStudent(student3)) {
 43             map.put(student3, getCurrentID());
 44         }
 45         
 46         Student student4 = new Student("赵六", 16);
 47         if (checkStudent(student4)) {
 48             map.put(student4, getCurrentID());
 49         }
 50         
 51         Student student5 = new Student("张三", 20);
 52         if (checkStudent(student5)) {
 53             map.put(student5, getCurrentID());
 54         }
 55         
 56         System.out.println("map:" + map);
 57         
 58         // 遍历映射
 59         for (Entry<Student, String> entry : map.entrySet()) {
 60             Student temp = entry.getKey();
 61             String id = entry.getValue();
 62             System.out.println("学号为:" + id + "," + temp.toString());
 63         }
 64     }
 65     
 66     // 获取当前可以使用的学号
 67     public static String getCurrentID() {
 68         String result = "1";
 69         
 70         if (map.size() > 0) {
 71             
 72             // 获取所有的学号,存入Collection对象
 73             Collection<String> collection = map.values();
 74             
 75             int max = 0;
 76             
 77             for (String item : collection) {
 78                 if (Integer.parseInt(item) > max) {
 79                     max = Integer.parseInt(item);
 80                 }
 81             }
 82             
 83             result = max + 1 + "";
 84         }
 85         
 86         return result;
 87     }
 88     
 89     // 判断学生信息是否有重复
 90     public static boolean checkStudent(Student student) {
 91         boolean flag = true;
 92         
 93         // 获取所有的学生信息,存入Set对象
 94         Set<Student> keySet = map.keySet();
 95         
 96         for (Student item : keySet) {
 97             if (item.equals(student)) {
 98                 flag = false;
 99                 break;
100             }
101         }
102         
103         return flag;
104     }
105 }
 1 package cn.temptation;
 2 
 3 // 学生类
 4 public class Student {
 5     // 成员变量
 6     private String name;
 7     private int age;
 8 
 9     // 构造函数
10     public Student() {
11         super();
12     }
13 
14     public Student(String name, int age) {
15         super();
16         this.name = name;
17         this.age = age;
18     }
19 
20     // 成员方法
21     public String getName() {
22         return name;
23     }
24 
25     public void setName(String name) {
26         this.name = name;
27     }
28 
29     public int getAge() {
30         return age;
31     }
32 
33     public void setAge(int age) {
34         this.age = age;
35     }
36     
37     // 为了唯一判断对象,重写hashCode方法和equals方法
38     @Override
39     public int hashCode() {
40         final int prime = 31;
41         int result = 1;
42         result = prime * result + age;
43         result = prime * result + ((name == null) ? 0 : name.hashCode());
44         return result;
45     }
46 
47     @Override
48     public boolean equals(Object obj) {
49         if (this == obj)
50             return true;
51         if (obj == null)
52             return false;
53         if (getClass() != obj.getClass())
54             return false;
55         Student other = (Student) obj;
56         if (age != other.age)
57             return false;
58         if (name == null) {
59             if (other.name != null)
60                 return false;
61         } else if (!name.equals(other.name))
62             return false;
63         return true;
64     }
65 
66     @Override
67     public String toString() {
68         return "学生 [姓名为:" + name + ", 年龄为:" + age + "]";
69     }
70 }
 1 package cn.temptation;
 2 
 3 import java.util.LinkedHashMap;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 
 7 public class Sample07 {
 8     public static void main(String[] args) {
 9         /*
10          * 类 LinkedHashMap<K,V>:Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。
11          * 
12          * 特点:
13          * 1、由HashMap保证唯一性
14          * 2、由链表保证有序性
15          */
16         Map<String, String> map = new LinkedHashMap<>();
17         
18         map.put("无冕之王", "荷兰");
19         map.put("桑巴军团", "巴西");
20         map.put("亚洲三流", "中国");
21         
22         for (Entry<String, String> entry : map.entrySet()) {
23             System.out.println("美称:" + entry.getKey() + " <-----> 国家名称:" + entry.getValue());
24         }
25     }
26 }
 1 package cn.temptation;
 2 
 3 import java.util.Map;
 4 import java.util.Map.Entry;
 5 import java.util.Set;
 6 import java.util.TreeMap;
 7 
 8 public class Sample08 {
 9     public static void main(String[] args) {
10         /*
11          * 类 TreeMap<K,V>:
12          * 基于红黑树(Red-Black tree)的 NavigableMap 实现。
13          * 该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。 
14          * 
15          * 用法:类比TreeSet
16          */
17         Map<String, String> map = new TreeMap<>();
18         
19         map.put("Q", "嬴政");
20         map.put("H", "刘彻");
21         map.put("T", "李世民");
22         map.put("S", "赵匡胤");
23         
24         for (Entry<String, String> entry : map.entrySet()) {
25             String key = entry.getKey();
26             String value = entry.getValue();
27             System.out.println(key + " <-----> " + value);
28         }
29         
30         System.out.println("------------------------------");
31         
32         Set<String> keySet = map.keySet();
33         System.out.println("keyset:" + keySet);
34         
35         for (String key : keySet) {
36             String value = map.get(key);
37             System.out.println(key + " <-----> " + value);
38         }
39     }
40 }
 1 package cn.temptation;
 2 
 3 import java.util.Comparator;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 import java.util.TreeMap;
 7 
 8 public class Sample09 {
 9     public static void main(String[] args) {
10         // 需求:使用TreeMap存储学生信息,姓名和年龄相同的学生只能存储一个,排序规则:先按年龄排序,年龄相同按姓名自然排序
11         
12         // 思路:姓名和年龄相同的学生只能存储一个,也就是把学生信息作为键;和TreeSet一样,自定义排序规则:通过实现Comparable接口 或 Comparator接口
13         
14         Map<Student, String> map = new TreeMap<>(new Comparator<Student>() {
15             @Override
16             public int compare(Student student1, Student student2) {
17                 // 先比较年龄
18                 int resultAge = student1.getAge() - student2.getAge();
19                 
20                 // 年龄相同比较姓名
21                 int result = (resultAge == 0) ? student1.getName().compareTo(student2.getName()) : resultAge;
22                 
23                 return result;
24             }
25         });
26         
27         map.put(new Student("张三", 20), "9526");
28         map.put(new Student("李四", 18), "9527");
29         map.put(new Student("王五", 20), "9528");
30         map.put(new Student("张三", 20), "9529");
31         
32         for (Entry<Student, String> entry : map.entrySet()) {
33             Student temp = entry.getKey();
34             String id = entry.getValue();
35             System.out.println("学号为:" + id + "," + temp.toString());
36         }
37     }
38 }
 1 package cn.temptation;
 2 
 3 import java.util.ArrayList;
 4 import java.util.LinkedHashMap;
 5 import java.util.Map;
 6 import java.util.Map.Entry;
 7 
 8 public class Sample10 {
 9     public static void main(String[] args) {
10         // 需求:选择合适的容器结构,存储并显示数据
11         // 类别:篮球明星前三名:乔丹、邓肯、科比
12         // 类别:足球明星前五名:梅西、C罗、卡卡、伊布、哈维
13         
14         // 思路:容器中可以再放入容器
15         
16         // 写法1、使用数组存储(注意:不同数组的索引同步)
17         // 声明类别数组
18         String[] arrCategory = { "篮球", "足球" };
19         // 声明球星数组
20         String[][] arrStar = { { "乔丹", "邓肯", "科比" }, { "梅西", "C罗", "卡卡", "伊布", "哈维" } };
21         
22         // 遍历数组
23         for (int i = 0; i < arrCategory.length; i++) {
24             StringBuffer sb = new StringBuffer();
25             sb.append("类别:").append(arrCategory[i]).append("中前").append(arrStar[i].length).append("名:");
26             
27             for (int j = 0; j < arrStar[i].length; j++) {
28                 sb.append(arrStar[i][j]).append("、");
29             }
30             
31             System.out.println(sb.substring(0, sb.length() - 1));
32         }
33         
34         System.out.println("--------------------------------------------------------");
35         
36         // 写法2、使用集合存储(整体使用Map映射,key存为类别,value存为存放了多个球星名字的ArrayList)
37         Map<String, ArrayList<String>> map = new LinkedHashMap<>();
38         
39         ArrayList<String> basketBallList = new ArrayList<>();
40         basketBallList.add("乔丹");
41         basketBallList.add("邓肯");
42         basketBallList.add("科比");
43         
44         map.put("篮球", basketBallList);
45         
46         ArrayList<String> soccerList = new ArrayList<>();
47         soccerList.add("梅西");
48         soccerList.add("C罗");
49         soccerList.add("卡卡");
50         soccerList.add("伊布");
51         soccerList.add("哈维");
52         
53         map.put("足球", soccerList);
54         
55         for (Entry<String, ArrayList<String>> entry : map.entrySet()) {
56             StringBuffer sb = new StringBuffer();
57             
58             String category = entry.getKey();
59             ArrayList<String> list = entry.getValue();
60             
61             sb.append("类别:").append(category).append("中前").append(list.size()).append("名:");
62             
63             for (String item : list) {
64                 sb.append(item).append("、");
65             }
66             
67             System.out.println(sb.substring(0, sb.length() - 1));
68         }
69     }
70 }
 1 package cn.temptation;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collection;
 5 import java.util.LinkedHashMap;
 6 import java.util.Map;
 7 import java.util.Map.Entry;
 8 
 9 public class Sample11 {
10     public static void main(String[] args) {
11         // 需求:
12         // 存储并显示2016年NBA东西部决赛
13         // 东部:克利夫兰<----->骑士、明尼苏达<----->森林狼
14         // 西部:休斯敦<----->火箭、金州<----->勇士
15         // 存储并显示2015年NBA东西部决赛
16         // 东部:克利夫兰<----->骑士、亚特兰大<----->老鹰
17         // 西部:洛杉矶<----->湖人、金州<----->勇士
18         
19         // 思路:复杂问题分解为若干个简单问题
20         
21         Map<String, String> map1 = new LinkedHashMap<>();
22         map1.put("克利夫兰", "骑士");
23         map1.put("明尼苏达", "森林狼");
24         
25         Map<String, String> map2 = new LinkedHashMap<>();
26         map2.put("休斯敦", "火箭");
27         map2.put("金州", "勇士");
28         
29         Map<String, Map<String, String>> mapArea2016 = new LinkedHashMap<>();
30         mapArea2016.put("东部", map1);
31         mapArea2016.put("西部", map2);
32         
33         // 把2016年的数据封装在对象中
34         Record record2016 = new Record();
35         record2016.setYear(2016);
36         record2016.setMapArea(mapArea2016);
37         
38         Map<String, String> map3 = new LinkedHashMap<>();
39         map3.put("克利夫兰", "骑士");
40         map3.put("亚特兰大", "老鹰");
41         
42         Map<String, String> map4 = new LinkedHashMap<>();
43         map4.put("洛杉矶", "湖人");
44         map4.put("金州", "勇士");
45         
46         Map<String, Map<String, String>> mapArea2015 = new LinkedHashMap<>();
47         mapArea2015.put("东部", map3);
48         mapArea2015.put("西部", map4);
49         
50         // 把2015年的数据封装在对象中
51         Record record2015 = new Record();
52         record2015.setYear(2015);
53         record2015.setMapArea(mapArea2015);
54         
55         // 创建存储数据记录的集合
56         Collection<Record> collectionNBA = new ArrayList<>();
57         collectionNBA.add(record2016);
58         collectionNBA.add(record2015);
59         
60         StringBuffer sb = new StringBuffer();
61 
62         // 遍历
63         for (Record record : collectionNBA) {
64             sb.append(record.getYear()).append("年NBA东西部决赛:").append("\r\n");
65                         
66             for (Entry<String, Map<String, String>> entryArea : record.getMapArea().entrySet()) {
67                 sb.append(entryArea.getKey()).append(":");
68                 
69                 Map<String, String> mapCity = entryArea.getValue();
70                 
71                 StringBuffer sbTemp = new StringBuffer();
72                 
73                 for (Entry<String, String> entry : mapCity.entrySet()) {
74                     sbTemp.append(entry.getKey()).append("<------>").append(entry.getValue()).append(",");
75                 }
76                 
77                 sb.append(sbTemp.substring(0, sbTemp.length() - 1));
78                 sb.append("\r\n");
79             }
80             
81             sb.append("\r\n");
82         }
83         
84         System.out.println(sb);
85     }
86 }
 1 package cn.temptation;
 2 
 3 import java.util.LinkedHashMap;
 4 import java.util.Map;
 5 
 6 /**
 7  * 数据记录类
 8  */
 9 public class Record {
10     // 成员变量
11     // 数据记录年份
12     private int year;
13     // 数据记录内容
14     private Map<String, Map<String, String>> mapArea = new LinkedHashMap<>();
15 
16     // 构造函数
17     public Record() {
18         super();
19     }
20 
21     public Record(int year, Map<String, Map<String, String>> mapArea) {
22         super();
23         this.year = year;
24         this.mapArea = mapArea;
25     }
26 
27     // 成员方法
28     public int getYear() {
29         return year;
30     }
31 
32     public void setYear(int year) {
33         this.year = year;
34     }
35 
36     public Map<String, Map<String, String>> getMapArea() {
37         return mapArea;
38     }
39 
40     public void setMapArea(Map<String, Map<String, String>> mapArea) {
41         this.mapArea = mapArea;
42     }
43 
44     @Override
45     public String toString() {
46         return "数据 [年份为:" + year + ", 内容为:" + mapArea + "]";
47     }
48 }
 1 package cn.temptation;
 2 
 3 import java.util.LinkedHashMap;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 
 7 public class Sample12 {
 8     public static void main(String[] args) {
 9         // 需求:使用集合相关知识统计"javaisgoodisbetterisbestisamazing"中各个字符出现的次数
10         //         显示:字符j:1次、字符a:4次、...
11         
12         // 思路:
13         // 1、既然统计的是字符出现的次数,所以把字符串转换为字符数组
14         // 2、创建一个map集合用来存储字符及其出现次数的关系映射,设置key为字符,value为出现次数
15         // 3、遍历字符数组,将得到的字符(key)传递map映射的get方法找到对应出现的次数(value)
16         //        A:如果返回值为null,说明map映射中没有该字符及其出现次数的映射关系,那么map中存储下来这个映射关系
17         //        B:如果返回值不为null,说明map映射中存在该字符及其出现次数的映射关系,那么将value值+1,再存储下来
18         
19         String str = "javaisgoodisbetterisbestisamazing";
20         char[] arr = str.toCharArray();
21         Map<Character, Integer> map = new LinkedHashMap<>();
22         
23         // 遍历字符数组
24         for (char item : arr) {
25             // 根据各个字符传入map集合中查找
26             Integer count = map.get(item);
27             
28             if (count == null) {
29                 // 如果返回值为null,说明map映射中没有该字符及其出现次数的映射关系,那么map中存储下来这个映射关系
30                 map.put(item, 1);
31             } else {
32                 // 如果返回值不为null,说明map映射中存在该字符及其出现次数的映射关系,那么将value值+1,再存储下来
33                 count++;
34                 // 注意:具有相同key的键值对,最新的键值对会覆盖之前的键值对
35                 map.put(item, count);
36             }
37         }
38         
39         // 遍历map集合
40         for (Entry<Character, Integer> entry : map.entrySet()) {
41             Character key = entry.getKey();
42             Integer value = entry.getValue();
43             System.out.println("字符" + key + ":" + value + "次");
44         }
45     }
46 }
 1 package cn.temptation;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collection;
 5 import java.util.Collections;
 6 import java.util.List;
 7 
 8 public class Sample13 {
 9     public static void main(String[] args) {
10         /*
11          * 类 Collections:
12          * 此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。
13          * 它包含在 collection 上操作的多态算法,即“包装器”,包装器返回由指定 collection 支持的新 collection,以及少数其他内容。 
14          * 
15          * Collections类的常用成员方法:
16          * 1、static <T extends Comparable<? super T>> void sort(List<T> list) :根据元素的自然顺序 对指定列表按升序进行排序。 
17          * 
18          * 2、static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) :使用二分搜索法搜索指定列表,以获得指定对象。
19          *         返回:如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。
20          *             插入点 被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都小于指定的键,则为 list.size()。
21          *             注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。
22          *  
23          * 3、static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) :根据元素的自然顺序,返回给定 collection 的最大元素。 
24          * 
25          * 4、static void reverse(List<?> list) :反转指定列表中元素的顺序。 
26          * 
27          * 5、static void shuffle(List<?> list) :使用默认随机源对指定列表进行置换。 
28          * 
29          */
30         
31         Collection<Integer> collection = new ArrayList<>();
32         
33         collection.add(2);
34         collection.add(3);
35         collection.add(5);
36         collection.add(4);
37         collection.add(1);
38         
39         System.out.println("初始集合:" + collection);        // 初始集合:[2, 3, 5, 4, 1]
40         
41         Collections.sort((List<Integer>)collection);
42         System.out.println("使用排序:" + collection);        // 使用排序:[1, 2, 3, 4, 5]
43         
44         System.out.println("二分查找:" + Collections.binarySearch((List<Integer>)collection, 2));        // 1
45         System.out.println("二分查找:" + Collections.binarySearch((List<Integer>)collection, 0));        // -1
46         System.out.println("二分查找:" + Collections.binarySearch((List<Integer>)collection, 5));        // 4
47         
48         System.out.println("最大值:" + Collections.max(collection));        // 5
49         
50         Collections.reverse((List<Integer>)collection);
51         System.out.println("使用反转:" + collection);        // 使用反转:[5, 4, 3, 2, 1]
52         
53         Collections.shuffle((List<Integer>)collection);
54         System.out.println("随机置换:" + collection);
55     }
56 }
 1 package cn.temptation;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collection;
 5 import java.util.Collections;
 6 import java.util.Comparator;
 7 import java.util.List;
 8 
 9 public class Sample14 {
10     public static void main(String[] args) {
11         /*
12          * Collections类的常用成员方法:
13          * 1、static <T> void sort(List<T> list, Comparator<? super T> c) :根据指定比较器产生的顺序对指定列表进行排序。 
14          */
15         Collection<Student> collection = new ArrayList<>();
16         
17         collection.add(new Student("张三", 20));
18         collection.add(new Student("李四", 18));
19         collection.add(new Student("王五", 22));
20         collection.add(new Student("张飞", 20));
21         
22         // 语法错误:The method sort(List<T>) in the type Collections is not applicable for the arguments (List<Student>)
23 //        Collections.sort((List<Student>)collection);
24         
25         Collections.sort((List<Student>)collection, new Comparator<Student>() {
26             @Override
27             public int compare(Student student1, Student student2) {
28                 // 先比较年龄
29                 int resultAge = student1.getAge() - student2.getAge();
30                 
31                 // 年龄相同再比较姓名
32                 int result = (resultAge == 0) ? student1.getName().compareTo(student2.getName()) : resultAge;
33                 
34                 return result;
35             }
36         });
37         
38         // 遍历
39         for (Student item : collection) {
40             System.out.println(item);
41         }
42     }
43 }
 1 package cn.temptation;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collection;
 5 import java.util.Collections;
 6 import java.util.List;
 7 
 8 public class Sample15 {
 9     public static void main(String[] args) {
10         // 需求:使用所学集合知识,模拟一副牌(54张)的洗牌、发牌(按照规则制作即可,规则选用一副牌斗地主)和看牌(无序)
11         // 牌:A、2、3、4、5、6、7、8、9、10、J、Q、K、BlackJoker、RedJoker
12         // 花色:♥ ◆ ♠ ♣
13         
14         // 思路:
15         // 1、创建出一副牌54张(4种花色每种13张,还有大王小王)
16         // 2、把牌放入一个容器中
17         // 3、洗牌(考虑使用集合工具类Collections的shuffle方法)
18         // 4、发牌
19         // 5、看牌
20         
21         // 1、创建出一副牌54张(4种花色每种13张,还有大王小王)
22         // 创建花色集合
23         Collection<String> colors = new ArrayList<>();
24         colors.add("♥");
25         colors.add("◆");
26         colors.add("♠");
27         colors.add("♣");
28         
29         // 创建数字集合
30         Collection<String> numbers = new ArrayList<>();
31         numbers.add("A");
32         for (int i = 2; i <= 10; i++) {
33             numbers.add(String.valueOf(i));
34         }
35         numbers.add("J");
36         numbers.add("Q");
37         numbers.add("K");
38         
39         // 2、把牌放入一个容器中
40         Collection<String> poker = new ArrayList<>();
41         
42         for (String color : colors) {
43             for (String number : numbers) {
44                 poker.add(color.concat(number));
45             }
46         }
47         
48         poker.add("BlackJoker");
49         poker.add("RedJoker");
50         
51 //        System.out.println("一副牌:" + poker);
52         
53         // 3、洗牌(考虑使用集合工具类Collections的shuffle方法)
54         Collections.shuffle((List<String>)poker);
55         
56 //        System.out.println("洗一副牌:" + poker);
57         
58         // 4、发牌
59         // 声明剩余底牌数量
60         int remain = 3;
61         // 声明三个玩家对象和一个底牌对象
62         Collection<String> player1 = new ArrayList<>();
63         Collection<String> player2 = new ArrayList<>();
64         Collection<String> player3 = new ArrayList<>();
65         Collection<String> last = new ArrayList<>();
66         
67         for (int i = 0; i < poker.size(); i++) {
68             if (i >= poker.size() - remain) {            // 留下底牌
69                 last.add(((List<String>)poker).get(i));
70             } else if (i % 3 == 0) {                    // 给第一个玩家发牌
71                 player1.add(((List<String>)poker).get(i));
72             } else if (i % 3 == 1) {                    // 给第二个玩家发牌
73                 player2.add(((List<String>)poker).get(i));
74             } else if (i % 3 == 2) {                    // 给第三个玩家发牌
75                 player3.add(((List<String>)poker).get(i));
76             }
77         }
78         
79         // 5、看牌
80         lookPoker("玩家1", player1);
81         lookPoker("玩家2", player2);
82         lookPoker("玩家3", player3);
83         lookPoker("底牌", last);
84     }
85     
86     /**
87      * 看牌方法
88      * @param name                玩家名
89      * @param collection        手牌集合
90      */
91     public static void lookPoker(String name, Collection<String> collection) {
92         System.out.println(name + "的手牌是:");
93         for (String item : collection) {
94             System.out.print(item + " ");
95         }
96         // 换行
97         System.out.println();
98     }
99 }
  1 package cn.temptation;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Collection;
  5 import java.util.Collections;
  6 import java.util.Comparator;
  7 import java.util.List;
  8 import java.util.Set;
  9 import java.util.TreeSet;
 10 
 11 public class Sample16 {
 12     public static void main(String[] args) {
 13         // 需求:使用所学集合知识,模拟一副牌(54张)的洗牌、发牌(按照规则制作即可,规则选用一副牌斗地主)和看牌(有序)
 14         // 牌:A、2、3、4、5、6、7、8、9、10、J、Q、K、BlackJoker、RedJoker
 15         // 花色:♥ ◆ ♠ ♣
 16         // 顺序规则:牌的规则:3 < 4 < 5 < ... < 10 < J < Q < K < A < 2 < BlackJoker < RedJoker
 17         //            花色的规则(牌相同时)♥ ♠ ♣ ◆
 18         
 19         // 思路1:
 20         // 在发牌时,通过比较器的使用,直接按规则排列玩家手中牌和底牌
 21         
 22         // 1、创建出一副牌54张(4种花色每种13张,还有大王小王)
 23         // 创建花色集合
 24         Collection<String> colors = new ArrayList<>();
 25         colors.add("♥");
 26         colors.add("◆");
 27         colors.add("♠");
 28         colors.add("♣");
 29         
 30         // 创建数字集合
 31         Collection<String> numbers = new ArrayList<>();
 32         numbers.add("A");
 33         for (int i = 2; i <= 10; i++) {
 34             numbers.add(String.valueOf(i));
 35         }
 36         numbers.add("J");
 37         numbers.add("Q");
 38         numbers.add("K");
 39         
 40         // 2、把牌放入一个容器中
 41         Collection<Card> poker = new ArrayList<>();
 42         
 43         for (String color : colors) {
 44             for (String number : numbers) {
 45                 Card temp = new Card();
 46                 temp.setColor(color);
 47                 temp.setNumber(number);
 48                 
 49                 poker.add(temp);
 50             }
 51         }
 52         
 53         poker.add(new Card("", "BlackJoker"));
 54         poker.add(new Card("", "RedJoker"));
 55         
 56 //        System.out.println("一副牌:" + poker);
 57         
 58         // 3、洗牌(考虑使用集合工具类Collections的shuffle方法)
 59         Collections.shuffle((List<Card>)poker);
 60         
 61 //        System.out.println("洗一副牌:" + poker);
 62         
 63         // 4、发牌
 64         // 声明剩余底牌数量
 65         int remain = 3;
 66         
 67         // 声明三个玩家对象和一个底牌对象
 68         Comparator<Card> comparator = new CardComparator();
 69         
 70         Set<Card> player1 = new TreeSet<>(comparator);
 71         Set<Card> player2 = new TreeSet<>(comparator);
 72         Set<Card> player3 = new TreeSet<>(comparator);
 73         Set<Card> last = new TreeSet<>(comparator);
 74         
 75         for (int i = 0; i < poker.size(); i++) {
 76             if (i >= poker.size() - remain) {            // 留下底牌
 77                 last.add(((List<Card>)poker).get(i));
 78             } else if (i % 3 == 0) {                    // 给第一个玩家发牌
 79                 player1.add(((List<Card>)poker).get(i));
 80             } else if (i % 3 == 1) {                    // 给第二个玩家发牌
 81                 player2.add(((List<Card>)poker).get(i));
 82             } else if (i % 3 == 2) {                    // 给第三个玩家发牌
 83                 player3.add(((List<Card>)poker).get(i));
 84             }
 85         }
 86         
 87         // 5、看牌
 88         lookPoker("玩家1", player1);
 89         lookPoker("玩家2", player2);
 90         lookPoker("玩家3", player3);
 91         lookPoker("底牌", last);
 92     }
 93     
 94     /**
 95      * 看牌方法
 96      * @param name                玩家名
 97      * @param collection        手牌集合
 98      */
 99     public static void lookPoker(String name, Set<Card> collection) {
100         System.out.println(name + "的手牌是:");
101         for (Card item : collection) {
102             System.out.print(item + " ");
103         }
104         // 换行
105         System.out.println();
106     }
107 }
 1 package cn.temptation;
 2 
 3 /**
 4  * 牌类
 5  */
 6 public class Card {
 7     // 成员变量
 8     // 花色
 9     private String color;
10     // 数字
11     private String number;
12     
13     // 构造函数
14     public Card() {
15         super();
16     }
17     
18     public Card(String color, String number) {
19         super();
20         this.color = color;
21         this.number = number;
22     }
23 
24     // 成员方法
25     public String getColor() {
26         return color;
27     }
28 
29     public void setColor(String color) {
30         this.color = color;
31     }
32 
33     public String getNumber() {
34         return number;
35     }
36 
37     public void setNumber(String number) {
38         this.number = number;
39     }
40 
41     @Override
42     public String toString() {
43         return color + number;
44     }
45 }
 1 package cn.temptation;
 2 
 3 import java.util.Comparator;
 4 
 5 /**
 6  * 牌的比较器
 7  */
 8 public class CardComparator implements Comparator<Card> {
 9     @Override
10     public int compare(Card card1, Card card2) {
11         // 首先比较数字
12         int resultNumber = numberChange(card1.getNumber()) - numberChange(card2.getNumber());
13         
14         // 数字相同时,比较花色
15         int result = (resultNumber == 0) ? colorChange(card1.getColor()) - colorChange(card2.getColor()) : resultNumber;
16         
17         return result;
18     }
19     
20     /**
21      * 手牌数字转换方法
22      * @param number    手牌数字
23      * @return            对应数字
24      */
25     public static int numberChange(String number) {
26         int result = 0;
27         
28         switch (number) {
29         case "J":
30             result = 11;
31             break;
32         case "Q":
33             result = 12;
34             break;
35         case "K":
36             result = 13;
37             break;
38         case "A":
39             result = 14;
40             break;
41         case "2":
42             result = 15;
43             break;
44         case "BlackJoker":
45             result = 16;
46             break;
47         case "RedJoker":
48             result = 17;
49             break;
50         default:
51             result = Integer.parseInt(number);
52             break;
53         }
54         
55         return result;
56     }
57     
58     /**
59      * 手牌花色转换方法
60      * @param color        手牌花色
61      * @return            对应数字
62      */
63     public static int colorChange(String color) {
64         int result = 0;
65         
66         switch (color) {
67         case "♥":
68             result = 1;
69             break;
70         case "♠":
71             result = 2;
72             break;
73         case "♣":
74             result = 3;
75             break;
76         case "◆":
77             result = 4;
78             break;
79         default:
80             break;
81         }
82         
83         return result;
84     }
85 }
  1 package cn.temptation;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Collection;
  5 import java.util.Collections;
  6 import java.util.HashMap;
  7 import java.util.List;
  8 import java.util.Map;
  9 import java.util.Set;
 10 import java.util.TreeSet;
 11 
 12 public class Sample17 {
 13     public static void main(String[] args) {
 14         // 需求:使用所学集合知识,模拟一副牌(54张)的洗牌、发牌(按照规则制作即可,规则选用一副牌斗地主)和看牌(有序)
 15         // 牌:A、2、3、4、5、6、7、8、9、10、J、Q、K、BlackJoker、RedJoker
 16         // 花色:♥ ◆ ♠ ♣
 17         // 顺序规则:牌的规则:3 < 4 < 5 < ... < 10 < J < Q < K < A < 2 < BlackJoker < RedJoker
 18         //            花色的规则(牌相同时)♥ ♠ ♣ ◆
 19         
 20         // 思路2:
 21         // 在发牌阶段进行排序比较麻烦,可以考虑在创建牌的时候,就把顺序订好,54张牌按照大小和花色有一个数字排序(索引)
 22         // 后续操作时,洗牌洗的就是这个数字顺序,看牌时每个人的手牌和底牌都按数字顺序排列就好
 23         
 24         // 1、创建出一副牌54张(4种花色每种13张,还有大王小王),花色顺序和数字顺序都定好
 25         // 2、牌不但有纸面内容(花色和数字),还有其索引,所以考虑使用Map存储
 26         // 3、洗牌(考虑使用集合工具类Collections的shuffle方法)
 27         // 4、发牌(发的也是牌的索引)
 28         // 5、看牌
 29         
 30         // 1、创建出一副牌54张(4种花色每种13张,还有大王小王),花色顺序和数字顺序都定好
 31         // 创建花色集合
 32         Collection<String> colors = new ArrayList<>();
 33         colors.add("♥");
 34         colors.add("♠");
 35         colors.add("♣");
 36         colors.add("◆");
 37         
 38         // 创建数字集合
 39         Collection<String> numbers = new ArrayList<>();
 40         for (int i = 3; i <= 10; i++) {
 41             numbers.add(String.valueOf(i));
 42         }
 43         numbers.add("J");
 44         numbers.add("Q");
 45         numbers.add("K");
 46         numbers.add("A");
 47         numbers.add("2");
 48         
 49         // 2、牌不但有纸面内容(花色和数字),还有其索引,所以考虑使用Map存储
 50         // 创建存放牌的容器
 51         Map<Integer, String> poker = new HashMap<>();
 52         // 创建存放牌的索引的容器(伴随着把牌放入Map对象中,索引放入Collection对象中)
 53         Collection<Integer> collection = new ArrayList<>();
 54         // 声明牌的索引变量
 55         int index = 0;
 56         
 57         // 注意:放牌进入map中顺序,先数字再花色
 58         for (String number : numbers) {
 59             for (String color : colors) {
 60                 // 把牌放入Map对象中
 61                 poker.put(index, color.concat(number));
 62                 // 把牌的索引放入Collection对象中
 63                 collection.add(index);
 64                 // 创建一张牌,索引自增
 65                 index++;
 66             }
 67         }
 68         
 69         // 创建小王
 70         poker.put(index, "BlackJoker");
 71         collection.add(index);
 72         index++;
 73         
 74         // 创建大王
 75         poker.put(index, "RedJoker");
 76         collection.add(index);
 77         index++;
 78         
 79         // 遍历map
 80 //        for (Entry<Integer, String> entry : poker.entrySet()) {
 81 //            System.out.println(entry.getKey() + "<----->" + entry.getValue());
 82 //        }
 83         
 84         // 3、洗牌(考虑使用集合工具类Collections的shuffle方法,洗的是牌的索引集合)
 85         Collections.shuffle((List<Integer>)collection);
 86         
 87 //        System.out.println("洗一副牌:" + collection);
 88         
 89         // 4、发牌(发的是牌的索引)
 90         // 声明剩余底牌数量
 91         int remain = 3;
 92         
 93         Set<Integer> player1 = new TreeSet<>();
 94         Set<Integer> player2 = new TreeSet<>();
 95         Set<Integer> player3 = new TreeSet<>();
 96         Set<Integer> last = new TreeSet<>();
 97         
 98         for (int i = 0; i < poker.size(); i++) {
 99             if (i >= poker.size() - remain) {            // 留下底牌
100                 last.add(((List<Integer>)collection).get(i));
101             } else if (i % 3 == 0) {                    // 给第一个玩家发牌
102                 player1.add(((List<Integer>)collection).get(i));
103             } else if (i % 3 == 1) {                    // 给第二个玩家发牌
104                 player2.add(((List<Integer>)collection).get(i));
105             } else if (i % 3 == 2) {                    // 给第三个玩家发牌
106                 player3.add(((List<Integer>)collection).get(i));
107             }
108         }
109         
110         // 5、看牌(根据键值对中的键去map中找值)
111         lookPoker("玩家1", player1, poker);
112         lookPoker("玩家2", player2, poker);
113         lookPoker("玩家3", player3, poker);
114         lookPoker("底牌", last, poker);
115     }
116     
117     /**
118      * 看牌方法
119      * @param name                玩家名
120      * @param collection        手牌集合
121      */
122     public static void lookPoker(String name, Set<Integer> collection, Map<Integer, String> map) {
123         System.out.println(name + "的手牌是:");
124         
125         for (Integer item : collection) {
126             System.out.print(map.get(item) + " ");
127         }
128         
129         // 换行
130         System.out.println();
131     }
132 }
 1 package cn.temptation;
 2 
 3 public class Sample18 {
 4     public static void main(String[] args) {
 5         /*
 6          * 集合总结:
 7          * Collection接口(单列集合):
 8          *         1、List接口(有序、可重复):
 9          *             A、ArrayList:底层实现是数组,查找快速、增删比较慢
10          *             B、Vector:向量类,ArrayList是其升级版,底层实现是数组,查找快速、增删比较慢,遍历向量对象可以使用枚举器(Enumeration)
11          *             C、LinkedList:底层实现是链表,查找比较慢、增删快速
12          * 
13          *         2、Set接口(无序、唯一):
14          *             A、HashSet:底层实现是哈希表、依赖于hashCode()和equals()
15          *             B、LinkedHashSet:底层实现是哈希表和链表组成,由哈希表保证元素唯一、由链表保证元素有序
16          *             C、TreeSet:支持自然排序和自定义规则排序(实现Comparable接口 或 Comparator接口)
17          * 
18          * Map接口(双列集合):
19          *             A、HashMap:底层实现是哈希表、依赖于hashCode()和equals()
20          *             B、LinkedHashMap:底层实现是哈希表和链表组成,由哈希表保证元素唯一、由链表保证元素有序
21          *             C、TreeMap:支持自然排序和自定义规则排序(实现Comparable接口 或 Comparator接口)
22          * 
23          * 
24          * 是否需要键值对:
25          *         是:选择Map,键是否需要排序
26          *                         是:选择TreeMap
27          *                         否:选择HashMap
28          *         否:选择Collection,元素是否需要唯一
29          *                         是:选择Set,元素是否需要排序
30          *                                         是:TreeSet
31          *                                         否:HashSet
32          *                         否:选择List,需要查找快速还是需要增删快速
33          *                                         查找快速:ArrayList
34          *                                         增删快速:LinkedList
35          * 
36          * 遍历元素:
37          * 1、一般for循环
38          * 2、迭代器(Iterator)或枚举器(Enumeration)
39          * 3、增强型for循环
40          * 
41          */
42     }
43 }

 

posted @ 2017-03-21 21:19  {name:"代码屠夫"}  阅读(1722)  评论(0编辑  收藏  举报