Java 基础篇:第十四章:Map集合和Collection工具类

目录

一、Map接口:

1.1 概述:

1.2 Map接口的方法:

1.3 Map集合的遍历:

1.4 案例分析(自定义类作为Map的键):

1.5 LinkedHashMap类:

1.6 TreeMap类:

1.7 集合嵌套之HashMap嵌套HashMap:

1.8 Hashtable类:

1.9 课后练习:

二、Collections工具类:

2.1 Collections工具类概述:

2.2 应用实例——斗地主(V1.0):

2.3 应用实例——斗地主(v2.0):


 

主要内容:

1、Map接口

2、HashMap

3、LinkedHashMap

4、TreeMap

5、HashTable

6、Collections工具类

                               

 

一、Map接口:

1.1 概述:

public interface Map<K,V>

将键映射到值的对象。

一个映射不能包含重复的键;【键唯一】

每个键最多只能映射到一个值。

 

Map和Collection的区别:

Collocation是单列的集合;Map是双列的集合。

Collection集合中List集合元素是不唯一的、Set集合元素是唯一的;Map的键(Key)是唯一的。

Collection集合的数据结构是针对元素有效;Map集合的数据结构值对键有效,跟值无关。

1.2 Map接口的方法:

1、添加:

V put(K key,V value)

将指定的值与此映射中的指定键关联(可选操作)。如果此映射以前包含一个该键的映射关系,则用指定值替换旧值(当且仅当 m.containsKey(k) 返回 true 时,才能说映射 m 包含键 k 的映射关系)。

2、删除:

V remove(Object key):如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

void clear():从此映射中移除所有映射关系(可选操作)。此调用返回后,该映射将为空。

3、长度:

int size()

返回此映射中的键-值映射关系数。如果该映射包含的元素大于 Integer.MAX_VALUE,则返回 Integer.MAX_VALUE。

4、获取功能:

V get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

Set<K> keySet():返回此映射中包含的键的 Set 视图。

Set<Map.Entry<K,V>> entrySet():返回此映射中包含的映射关系的 Set 视图。

Collection<V> values():返回此映射中包含的值的 Collection 视图。

5、判断功能:

boolean isEmpty():如果此映射未包含键-值映射关系,则返回 true。

boolean containsKey(Object key:如果此映射包含指定键的映射关系,则返回 true。

boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回 true。

public class MapDemo01 {

    public static void main(String[] args) {

       // 1、添加

       Map<Integer, String> map = new HashMap<Integer, String>();

       map.put(1, "zhangqiang");

       map.put(2, "wangjian");

       map.put(3, null);

       // 3、长度:int size()

       System.out.println("初始化的元素个数:" + map.size());

       // 2、删除

       // map.remove(3);

       // System.out.println("删除3-null之后的元素个数为:" + map.size());

       // map.clear();

       // System.out.println("执行clear之后的元素个数为:" + map.size());

       // 4、获取功能:

       String stu = map.get(2);

       System.out.println("stu:" + stu);

       Set<Integer> keys = map.keySet(); // 全部的key组成集合

       for (Integer key : keys) {

           System.out.println("key:" + key);

       }

       // 遍历map集合中全部的value

       Set<Map.Entry<Integer, String>> values = map.entrySet();

       for (Map.Entry<Integer, String> value : values) {

           System.out.println("value:" + value.getValue());

       }

       // 获取集合中所有值的集合

       Collection<String> values2 = map.values();

       // 转换数组遍历或转换成Iterator

       Iterator<String> iterator = values2.iterator();

       while (iterator.hasNext()) {

           System.out.println("value2:" + iterator.next());

       }

       // 5、判断功能

       System.out.println(map.isEmpty());

       System.out.println(map.containsKey(4));

       System.out.println(map.containsValue("yougen"));

    }

}

1.3 Map集合的遍历:

Map集合不能直接使用Iterator,因为Map接口中未声明跟Iterator相关的方法。

方式一:使用Map的entrySet()方法

方式二:使用Map的keySet()方法和get(Object key)方法

public class MapDemo02 {

    public static void main(String[] args) {

       Map<Integer, String> table = new HashMap<Integer, String>();

       table.put(1, "小亮");

       table.put(2, "克弘");

       table.put(3, "俊杰");

       table.put(4, "欧阳");

 

       // keySet()——获取全部key

       // values()——获取全部value

       // entrySet()——返回值是Set<Map.Entry<Integer,String>>类型

       // 现在要求获取全部的key-value

       // 1、第一种方式;

       // print1(table);

 

       // 2、第二种方式:

       print2(table);

    }

 

    public static void print2(Map<Integer, String> map) {

       Set<Integer> keySet = map.keySet();

       for (Integer key : keySet) {

           System.out.println(key + "=" + map.get(key));

       }

    }

 

    public static void print1(Map<Integer, String> map) {

       Set<Map.Entry<Integer, String>> entrys = map.entrySet();

       for (Map.Entry<Integer, String> en : entrys) {

           System.out.println(en);

       }

    }

}

 

 

补充:Entry类的源码分析

Ctrl+Shift+T  找类库中和用户自定义的类或接口

Ctrl+O  在类中查找方法

1、打印Set集合时,可以直接使用集合名称,而不需要遍历。

public static void printMap(Map<Integer, String> map) {

       // 1、先获得全部的key,再根据key获取value

       Set<Integer> keySet = map.keySet();

       for (Integer key : keySet) {

           System.out.println(key + "=" + map.get(key));

       }

       System.out.println("--------------------");

       // 2、第二种方式:

       Set<Map.Entry<Integer, String>> entrySet = map.entrySet();

       // HashSet类实现Set接口; HashSet extends AbstractSet extends

       // AbstractCollection;AbstractCollection类中实现了toString方法,打印set集合可以直接使用集合名称

       for (Map.Entry<Integer, String> en : entrySet) {

           System.out.println(en);

       }

       System.out.println(entrySet); // toString()

    }

2、Map接口中的Entry接口是由HashMap中内部类Entry实现的:

 

 

1.4 案例分析(自定义类作为Map的键):

HashMap集合键是Student、值是String的案例:

注意:必须要重写Student类(用户自定义类)的equals方法和hashCode方法。

public class Student {

    private String name;

    private Integer age;

 

    @Override

    public String toString() {

       StringBuilder builder = new StringBuilder();

       builder.append("Student [name=");

       builder.append(name);

       builder.append(", age=");

       builder.append(age);

       builder.append("]");

       return builder.toString();

    }

 

    @Override

    public int hashCode() {

       final int prime = 31;

       int result = 1;

       result = prime * result + ((age == null) ? 0 : age.hashCode());

       result = prime * result + ((name == null) ? 0 : name.hashCode());

       return result;

    }

 

    @Override

    public boolean equals(Object obj) {

       if (this == obj)

           return true;

       if (obj == null)

           return false;

       if (getClass() != obj.getClass())

           return false;

       Student other = (Student) obj;

       if (age == null) {

           if (other.age != null)

              return false;

       } else if (!age.equals(other.age))

           return false;

       if (name == null) {

           if (other.name != null)

              return false;

       } else if (!name.equals(other.name))

           return false;

       return true;

    }

 

    public Student() {

       super();

    }

 

    public Student(String name, Integer age) {

       super();

       this.name = name;

       this.age = age;

    }

 

    public String getName() {

       return name;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public Integer getAge() {

       return age;

    }

 

    public void setAge(Integer age) {

       this.age = age;

    }

}

 

public class MapDemo02 {

    // 以Student为键,String为值的Map集合

    public static void main(String[] args) {

       Map<Student, String> work = new HashMap<Student, String>();

       // 直接向下复制整行:Ctrl+Down;

       // 修改打开preferences,搜索keys:copy-lines

       work.put(new Student("有根", 24), "深圳");

       work.put(new Student("惠明", 23), "北京");

       work.put(new Student("惠明", 23), "北京");

       work.put(new Student("王健", 23), "上海");

       // Map集合也可以直接打印

       System.out.println(work); // toString()

    }

}

 

1.5 LinkedHashMap类:

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入 键,则插入顺序不受影响。

public class MapDemo03 {

    // 以Student为键,String为值的Map集合,用LinkedHashMap实现

    public static void main(String[] args) {

       Map<Student, String> work = new LinkedHashMap<Student, String>();

       work.put(new Student("王健", 23), "上海");

       work.put(new Student("惠明", 23), "北京");

       work.put(new Student("有根", 24), "深圳");

 

       work.put(new Student("惠明", 23), "广州");

       System.out.println(work); // toString()

    }

}

 

1.6 TreeMap类:

TreeMap集合键是Person、值是String的案例

1、Person类实现Comparable接口保证顺序:

public class Person implements Comparable<Person> {

    private String name;

    private Integer age;

 

    public String getName() {

       return name;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public Integer getAge() {

       return age;

    }

 

    public void setAge(Integer age) {

       this.age = age;

    }

 

    public Person(String name, Integer age) {

       super();

       this.name = name;

       this.age = age;

    }

 

    public Person() {

       super();

       // TODO Auto-generated constructor stub

    }

 

    @Override

    public String toString() {

       StringBuilder builder = new StringBuilder();

       builder.append("Person [name=");

       builder.append(name);

       builder.append(", age=");

       builder.append(age);

       builder.append("]");

       return builder.toString();

    }

 

    @Override

    public int compareTo(Person person) { // this VS person

       // 假设先比较年龄(升序),如果年龄相同则比较姓名

       int num = this.getAge() - person.getAge();

       int num2 = this.getName().compareTo(person.getName());

       return num == 0 ? (num2 == 0 ? 1 : num2) : num;

    }

}

public class TreeMapDemo04 {

    public static void main(String[] args) {

       Map<Person, String> work = new TreeMap<Person, String>();

       work.put(new Person("有根", 22), "深圳");

       work.put(new Person("小亮", 20), "上海");

       work.put(new Person("发生", 21), "广州");

       work.put(new Person("克弘", 21), "广州");

       System.out.println(work);

    }

}

2、使用TreeMap的有参构造器:

TreeMap(Comparator<? super K> comparator)

          构造一个新的、空的树映射,该映射根据给定比较器进行排序。

public class Boss {

    private String name;

    private Integer age;

 

    public String getName() {

       return name;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public Integer getAge() {

       return age;

    }

 

    public void setAge(Integer age) {

       this.age = age;

    }

 

    public Boss(String name, Integer age) {

       super();

       this.name = name;

       this.age = age;

    }

 

    public Boss() {

       super();

       // TODO Auto-generated constructor stub

    }

 

    @Override

    public String toString() {

       StringBuilder builder = new StringBuilder();

       builder.append("Boss [name=");

       builder.append(name);

       builder.append(", age=");

       builder.append(age);

       builder.append("]");

       return builder.toString();

    }

}

public class TreeMapDemo05 {

    public static void main(String[] args) {

       Map<Boss, String> work = new TreeMap<Boss, String>(

              new Comparator<Boss>() { // 匿名类

                  @Override

                  public int compare(Boss boss1, Boss boss2) {

                     // 先比较年龄,如果年龄相同再比较姓名

                     int num1 = boss1.getAge() - boss2.getAge();

                     int num2 = boss1.getName().compareTo(boss2.getName());

                     return num1 == 0 ? (num2 == 0 ? 1 : num2) : num1;

                  }

              });

       work.put(new Boss("发生", 31), "广州");

       work.put(new Boss("有根", 32), "深圳");

       work.put(new Boss("小亮", 30), "上海");

       work.put(new Boss("克弘", 31), "广州");

       System.out.println(work);

    }

}

 

1.7 集合嵌套之HashMap嵌套HashMap:

public class HashMapHashMapDemo06 {

    /*

     * 15年之后,统计大家的就业情况:学生来自不同的班级(期)【“表-班级”的映射】,每个表之下会有“学生-公司”映射 *

     * Map<Map<学生对象,公司>,班级>

     */

    public static void main(String[] args) {

       // 定义一个Map代表Java76期班

       Map<Boss, String> java76 = new HashMap<Boss, String>();

       java76.put(new Boss("王总", 37), "华为");

       java76.put(new Boss("许总", 38), "Tencent");

 

       // 定义一个map代表UI75期班

       Map<Boss, String> ui75 = new HashMap<Boss, String>();

       ui75.put(new Boss("王书记", 35), "应用科技学院");

       ui75.put(new Boss("赵总", 36), "阿里巴巴");

 

       // 定义Map集合,代表所有学生的统计

       Map<Map<Boss, String>, String> total = new HashMap<Map<Boss, String>, String>();

       total.put(java76, "Java76班");

       total.put(ui75, "UI75班");

 

       // System.out.println(total);

       // 遍历双列集合

       for (Map<Boss, String> map : total.keySet()) {

           String className = total.get(map); // 获取到班级名称

           // map代表total的键,同时也代表某一个班级的全部就业情况

           for (Boss boss : map.keySet()) {

              String company = map.get(boss); // 获取到现在的就业公司

              System.out.println("boss:" + boss + ";company:" + company

                     + ";className:" + className);

           }

       }

    }

}

1.8 Hashtable类:

面试:HashMap和Hashtable的异同?

1、null键和null值的区别:

HashMap中可以存储null键和null值;Hashtable不允许存储null键和null值。

2、线程安全和效率上区别:

HashMap是JDK1.2版本提出的,线程不安全的,效率高;Hashtable是JDK1.0版本提出的,线程安全的,效率低。

public class HashtableDemo07 {

    public static void main(String[] args) {

       // 在HashMap中,键值对的值允许为null,键也允许为null,甚至键和值都可以为null

       Map<String, Integer> map1 = new HashMap<String, Integer>();

       map1.put("王老板", 7);

       map1.put("许老板", null);

       map1.put(null, null);

       System.out.println(map1);

 

       // Hashtable中,。不允许存储null键和null值

       Map<String, Integer> map2 = new Hashtable<String, Integer>();

       map2.put("钟总", 20);

       // map2.put("马总", null); // 错误,值不允许为null

       // map2.put(null, 21); // 错误,键不允许为null

       System.out.println(map2);

    }

}

1.9 课后练习:

需求:统计字符串中每个字符出现的次数。

如”aaaaabbbbbcccaass”,打印以下结果:

a:7

b:5

c:3

s:2

public class CountChar {

    /*

     * 需求:统计字符串中每个字符出现的次数。 如”aaaaabbbbbcccaass”,打印以下结果: a:7,b:5,c:3,s:2

     */

 

    // 1、定义一个需要统计的字符串(键盘录入)

    // 2、字符串转换成字符数组

    // 3、定义一个Map,存储“字符-次数”对应关系

    // 4、遍历数组,目的是要把字符和次数存储到map集合中

    // 5、先判断map集合中的key是否包含当前字符,如果不包含,就把该字符存储到map中,次数设置为1;如果包含,把map集合中该字符key对应的value加1

    // 6、打印

    public static void main(String[] args) {

       String str = "abdcslabbbcdss";

       char[] arr = str.toCharArray(); // 字符数组

       Map<Character, Integer> map = new HashMap<Character, Integer>();

       for (char ch : arr) { // ch代表当前指定的某个字符

           if (map.containsKey(ch)) { // map中包含该字符

              map.put(ch, map.get(ch) + 1);

           } else { // map不包含该字符

              map.put(ch, 1);

           }

       }

       // 打印

       // System.out.println(map);

       for (Character key : map.keySet()) {

           System.out.println(key + ":" + map.get(key));

       }

    }

}

 

二、Collections工具类:

2.1 Collections工具类概述:

public class Collections extends Object

此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。

 

public static <T> void sort(List<T> list)  排序(自然升序)

                   public static <T> int binarySearch(List<?> list,T key)  使用二分搜索法搜索指定列表,以获得指定对象。(如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。 插入点 被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都小于指定的键,则为 list.size()。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。)

                   public static <T> T max(Collection<?> coll)

                   public static void reverse(List<?> list)

                   public static void shuffle(List<?> list)

public class Demo01 {

    public static void main(String[] args) {

 

       List<String> list = new ArrayList<String>();

       list.add("A");

       list.add("B");

       list.add("D");

       list.add("E");

       list.add("I");

       list.add("C");

 

       System.out.println(list);

       // 1、排序,与Arrays.sort(char[] arr)排序类似

       // Collections.sort(list);

       // System.out.println(list);

 

       // 2、二分搜索法

       // int indexB = Collections.binarySearch(list, "B");

       // System.out.println("index of B:" + indexB);

       // int indexG = Collections.binarySearch(list, "G");

       // System.out.println("index of G:" + indexG);

 

       // 3、最值max min

       // System.out.println("max:" + Collections.max(list));

 

       // 4、反转:reverse

       // Collections.reverse(list);

       // System.out.println(list);

 

       // 5、洗牌:shuffle

       // Collections.shuffle(list);

       // System.out.println(list);

       // [E, D, C, A, B, I]

       // [D, B, A, E, I, C]

    }

}

 

 

2.2 应用实例——斗地主(V1.0):

public class Demo02 {

    // 模拟斗地主,洗牌、发牌、看牌。牌没有顺序

    // 1、创建一个集合,把牌装进去

    // 2、洗牌:shuffle

    // 3、发牌:三个人+3张底牌

    // 4、看牌(打印)

    public static void main(String[] args) {

       // 一、买了一副牌

       List<String> poker = new ArrayList<String>();

       // 四种花色

       String[] color = { "黑桃", "红桃", "梅花", "方片" };

       // 13个数字

       String[] num = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10",

              "J", "Q", "K" };

       for (String cl : color) {

           for (String nu : num) {

              poker.add(cl + nu);

           }

       }

       // System.out.println(poker);

       poker.add("大王");

       poker.add("小王");

       // System.out.println(poker);

       // 二、洗牌:

       Collections.shuffle(poker);

       // 三、发牌

       List<String> player1 = new ArrayList<String>();

       List<String> player2 = new ArrayList<String>();

       List<String> player3 = new ArrayList<String>();

       List<String> other = new ArrayList<String>();

       for (int i = 0; i < poker.size(); i++) {

           if (i < 3) {

              other.add(poker.get(i));

           } else { // i>=3

              if (i % 3 == 0) {

                  player1.add(poker.get(i));

               } else if (i % 3 == 1) {

                  player2.add(poker.get(i));

              } else {

                  player3.add(poker.get(i));

              }

           }

       }

       // 四、看牌

       System.out.println("player1:" + player1);

       System.out.println("player2:" + player2);

       System.out.println("player3:" + player3);

       System.out.println("other:" + other);

    }

}

使用List集合实现的,不能保证顺序?

2.3 应用实例——斗地主(v2.0):

public class Demo03 {

    // 模拟斗地主,洗牌、发牌、看牌。牌没有顺序

    // 1、创建一个集合,把牌装进去

    // 2、洗牌:shuffle

    // 3、发牌:三个人+3张底牌

    // 4、看牌(打印)

    public static void main(String[] args) {

       // 一、创建牌

       Map<Integer, String> poker = new HashMap<Integer, String>();

       // 花色

       String[] color = { "方片", "梅花", "红桃", "黑桃" };

       // 数字

       String[] num = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",

              "K", "A", "2" };

       List<Integer> list = new ArrayList<Integer>();

       int index = 0; // 索引

       // 拼接

       for (String n : num) {

           for (String c : color) {

              list.add(index); // 把0-51添加到list中

              poker.put(index, c + n);

              index++;

           }

       }

       // 有前面的52张牌

       // System.out.println(index);

       list.add(index);

       poker.put(index, "小王");

       index++;

       list.add(index);

       poker.put(index, "大王");

       // System.out.println(list);

 

       // 二、洗牌

       Collections.shuffle(list);

       // System.out.println(list);

 

       // 三、发牌

       Set<Integer> player1 = new TreeSet<Integer>();

       Set<Integer> player2 = new TreeSet<Integer>();

       Set<Integer> player3 = new TreeSet<Integer>();

       Set<Integer> other = new TreeSet<Integer>();

       for (int i = 0; i < list.size(); i++) {

           if (i >= list.size() - 3) {

              other.add(list.get(i));

           } else {

              if (i % 3 == 0) {

                  player1.add(list.get(i));

              } else if (i % 3 == 1) {

                  player2.add(list.get(i));

              } else {

                  player3.add(list.get(i));

              }

           }

       }

 

       // 四、看牌

       show(player1, poker, "惠明的牌");

       show(player2, poker, "有根的牌");

       show(player3, poker, "发生的牌");

       show(other, poker, "底牌");

    }

 

    public static void show(Set<Integer> set, Map<Integer, String> map,

           String player) {

       System.out.println(player + "是:");

       StringBuilder sb = new StringBuilder();

       for (Integer key : set) {

           sb.append(map.get(key) + ",");

       }

       System.out.println(sb.deleteCharAt(sb.lastIndexOf(",")));

    }

}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逼哥很疯狂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值