当前位置: 代码迷 >> 综合 >> JAVASE-21:Map集合及其子类HashMap 、Hashtable、LinkedHashMap 、TreeMap
  详细解决方案

JAVASE-21:Map集合及其子类HashMap 、Hashtable、LinkedHashMap 、TreeMap

热度:70   发布时间:2024-02-08 16:15:34.0

集合Map

有一种数据比较常见,比如一个学号对应一个学生,这种键值映射关系的数据,为了方便操作,给我们提供了另一种容器,叫做Map:称之为双列集合,有键 有映射值,一个键只能映射一个值,键是唯一的,如果键相同,那么值会覆盖。
所有的双列集合的数据结构,只跟键有关,跟值没有关系。

Map接口和Collection接口的不同
Map是双列的,Collection是单列的;
Map的键唯一,Collection的子体系Set是唯一的;
Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效。

接口Map<K,V>
K-此映射所维护的键的类型
V-映射值类型
实现类 HashMap<K,V> 、Hashtable<K,V>、 LinkedHashMap<K,V> 、 TreeMap<K,V>


1.HashMap<K,V>

键的数据结构是哈希表,所以键无序且唯一。允许null值 null键。线程不安全,效率高。所有的双列集合的数据结构,只跟键有关,跟值没有关系。当键相同,值就覆盖,返回的是上一次这个键所映射的那个旧值。

hm.put(“ K key”,“ V value”); 添加功能,这个其实还有另一个功能:替换—
如果键是第一次存储,就直接存储元素,返回null;
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

hm.clear(); 清空

hm.remove(K); 根据键值删除,返回值是键所对应的值

hm.size(); 集合长度

判断相关

判断是否有某个键 hm.containsKey(K);

判断是否有某个值 hm.containsValue(V);

通过键获取值 hm.get(K); 如果没有这个键返回null

通过键获取值 hm.getOrDefault(K,备用V); 如果没有这个键返回备用值

判断是否为空 hm.isEmpty();

hm.values(); 获取所有值得集合 放入collection

public static void main(String[] args) {HashMap<String, String> hm = new HashMap<>();hm.put("米兰", "马尔蒂尼");hm.put("国米", "萨内蒂");hm.put("尤文", "皮耶罗");hm.put("罗马", "托蒂");// hm.clear();清空集合// hm.size() 集合的长度System.out.println(hm.size());// 返回的是那个键,所对应的值。String s = hm.remove("罗马");System.out.println(hm);System.out.println(s);System.out.println(hm.containsKey("佛罗伦萨"));// falseSystem.out.println(hm.containsValue("马尔蒂尼"));// trueSystem.out.println(hm.isEmpty());// false//通过键来获取值System.out.println(hm.get("国米"));// 萨内蒂//通过键来获取值,没有对应的值,可以给一个默认值。System.out.println(hm.getOrDefault("佛罗伦萨", "巴蒂斯图塔"));// 巴蒂斯图塔
}
遍历双链集合

方式一:按照键找值,拿出所有键放入set集合,hm.keySet(); 获取所有键的集合,最后hm.get(K)按键找值。

方式二:将键值对,看作一个整体,把键值对 对象获取出来,然后使用键值对,对象中的方法获取键和值。

Map.Entry<String, String> ,K getKey () 返回与此项对应的键。 V getValue () 返回与此项对应的值。

方法三:forEach();

public static void main(String[] args) {HashMap<String, String> hm = new HashMap<>();hm.put("皇马", "BBC");hm.put("巴萨", "MSN");hm.put("拜仁", "罗贝里");hm.put("曼联", "林加德");// values();获取所有值的集合Collection<String> values = hm.values();System.out.println(values);// 遍历双列集合// 第一种:键找值 keySet();获取所有键的集合Set<String> keySet = hm.keySet();for (String key : keySet) {String value = hm.get(key);//按照键找值System.out.println(key + "===" + value);}System.out.println("=====================================");//第二种:把键值对,看做一个整体,把键值对,对象获取出来,然后使用键值对,对象中的方法来获取键和值。Set<Map.Entry<String, String>> entries = hm.entrySet();for (Map.Entry<String, String> entry : entries) {//System.out.println(entry);String key = entry.getKey();// 返回与此项对应的键String value = entry.getValue();// 返回与此项对应的值System.out.println(key + "===" + value);}//方法三:System.out.println("================================");hm.forEach(new BiConsumer<String, String>() {@Overridepublic void accept(String key, String value) {System.out.println(key + "===" + value);}});
}

所有的双列集合的数据结构,只跟键有关,跟值没有关系。

理解:new student虽然设置的成员变量name、age相同,但是两个都可以存进去,没有重写equales()和hashcode()方法,比较就认为地址值不同。

public static void main(String[] args) {// 存储键是Student类型,值是String类型HashMap<Student, String> hm = new HashMap<>();hm.put(new Student("张三", 23),"s001" );hm.put(new Student("张三", 23),"s001" );hm.put(new Student("王五", 25),"s002" );hm.put(new Student("赵六", 26),"s003" );hm.put(new Student("田七", 27),"s004" );for (Map.Entry<Student, String> entry : hm.entrySet()) {Student key = entry.getKey();String value = entry.getValue();System.out.println(key.getName()+"#"+key.getAge()+"===="+value);}
}

2.Hashtable<K,V>

和HashMap<K,V>的区别:

Hashtable<K,V> 不允许null值 和 null键,线程安全,效率低。

public static void main(String[] args) {HashMap<String, String> stringStringHashMap = new HashMap<>();stringStringHashMap.put(null,null);System.out.println(stringStringHashMap);Hashtable<String, String> stringStringHashtable = new Hashtable<>();//stringStringHashtable.put(null,"abc");stringStringHashtable.put("abc", null);//NullPointerException
}

3.LinkedHashMap<K,V>

键的数据结构是链表和哈希表,键唯一且有序,链表保证有序,哈希表保证唯一。

public static void main(String[] args) {// LinkedHashMap 键的数据结构是链表和哈希表,键唯一且有序,链表保证有序,哈希表保证唯一。LinkedHashMap<String, String> hm = new LinkedHashMap<>();hm.put("拜仁", "莱万");hm.put("拜仁","克洛泽");hm.put("多特", "哈兰德");hm.put("莱比锡", "维尔纳");hm.put("勒沃库森", "哈佛茨");System.out.println(hm);// {拜仁=克洛泽, 多特=哈兰德, 莱比锡=维尔纳, 勒沃库森=哈佛茨}
}

4.TreeMap<K,V>

TreeMap 键不允许插入null, 键的数据结构是红黑树,可保证键的排序和唯一性,排序分为自然排序和比较器排序 , 线程是不安全的效率比较高。

public static void main(String[] args) {TreeMap<Integer, String> treeMap = new TreeMap<>();treeMap.put(7, "舍甫琴科");treeMap.put(3, "马尔蒂尼");treeMap.put(1, "迪达");treeMap.put(21, "皮尔洛");treeMap.put(10, "鲁伊科斯塔");treeMap.put(9, "因扎吉");treeMap.put(2, "卡福");treeMap.put(13, "内斯塔");treeMap.put(5, "科斯塔库塔");treeMap.put(8, "加图索");Set<Integer> integers = treeMap.keySet();for (Integer integer : integers) {System.out.println(integer+"-"+treeMap.get(integer));}System.out.println();TreeMap<String, Integer> Milan = new TreeMap<>();Milan.put("Shevchenko",7);Milan.put("KaKa",22);Milan.put("Cafu",2);Milan.put("Gattuso",8);Milan.put("Nesta",13);Milan.put("Tomasson",15);Milan.put("Costa",10);Set<Map.Entry<String, Integer>> entries = Milan.entrySet();for (Map.Entry<String, Integer> entry : entries) {String key = entry.getKey();Integer value = entry.getValue();System.out.println(key +"-"+ value);}}

自然排序

public static void main(String[] args) {// 键是Student类型,值是String类型// 按照学生的年龄大小来排序TreeMap<Student, String> treeMap = new TreeMap<>();treeMap.put(new Student("张国荣", 18), "s001");treeMap.put(new Student("张国荣", 18), "s001");treeMap.put(new Student("张世豪", 15), "s004");treeMap.put(new Student("张世荣", 17), "s002");treeMap.put(new Student("张学友", 18), "s003");treeMap.put(new Student("张三", 18), "s004");treeMap.put(new Student("张曼玉", 17), "s005");/* System.out.println(treeMap); */treeMap.forEach(new BiConsumer<Student, String>() {@Overridepublic void accept(Student student, String s) {System.out.println(student.getName()+"=="+student.getAge()+"========="+s);}});
}
@Override
public int compareTo(Student o) {int num=this.age-o.age==0?this.name.compareTo(o.name):this.age-o.age;return num;
}

比较器排序

public static void main(String[] args) {TreeMap<Student, String> treeMap = new TreeMap<>(new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {int num = s1.getAge() - s2.getAge() == 0 ? s1.getName().compareTo(s2.getName()) : s1.getAge() - s2.getAge();return num;}});treeMap.put(new Student("张国荣", 18), "s001");treeMap.put(new Student("张国荣", 18), "s001");treeMap.put(new Student("张世豪", 15), "s004");treeMap.put(new Student("张世荣", 17), "s002");treeMap.put(new Student("张学友", 18), "s003");treeMap.put(new Student("张三", 18), "s004");treeMap.put(new Student("张曼玉", 17), "s005");// System.out.println(treeMap);treeMap.forEach(new BiConsumer<Student, String>() {@Overridepublic void accept(Student student, String s) {System.out.println(student.getName() + "==" + student.getAge() + "=========" + s);}});
}

练习1:

统计字符串中字符出现次数

“aababcabcdabcde”, 获取字符串中每一个字母出现的次数

要求结果:a(5) b(4) c(3) d(2) e(1)
a—5
b—4
c—3
d—2
e—1
每个字符和它出现的次数,是键值映射关系

public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入一段字符串");String str = sc.nextLine();// 每个字符和它出现的次数,是键值映射关系HashMap<Character, Integer> hashMap = new HashMap<>();for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);if (!hashMap.containsKey(ch)) {hashMap.put(ch, 1);} else {Integer value = hashMap.get(ch);value++;// 键相同,值覆盖hashMap.put(ch, value);}}System.out.println(hashMap);// 遍历集合拼串StringBuilder sb = new StringBuilder();for (Map.Entry<Character, Integer> entry : hashMap.entrySet()) {Character key = entry.getKey();Integer value = entry.getValue();sb.append(key).append("(").append(value).append(")").append(" ");}String s = sb.toString();System.out.println(s);

练习2:集合嵌套 - - - 先看小的关系 再看大的关系

HashMap嵌套HashMap

public static void main(String[] args) {/* * 基础班张三 20李四 22就业班王五 21赵六 23* *///HashMap 嵌套 HashMapHashMap<String, Integer> jcMap = new HashMap<>();jcMap.put("张三",20);jcMap.put("李四",22);HashMap<String, Integer> jyMap = new HashMap<>();jyMap.put("王五", 21);jyMap.put("赵六", 23);HashMap<String, HashMap<String, Integer>> maxMap = new HashMap<>();maxMap.put("基础班",jcMap);maxMap.put("就业班",jyMap);Set<String> keySet = maxMap.keySet();for (String s : keySet) {System.out.println(s);HashMap<String, Integer> minMap = maxMap.get(s);Set<String> keySet1 = minMap.keySet();for (String s1 : keySet1) {System.out.println("\t" +s1+" "+ minMap.get(s1));}}}

HashMap嵌套ArrayList

public static void main(String[] args) {/* * 三国演义吕布周瑜笑傲江湖令狐冲林平之神雕侠侣郭靖杨过* */ArrayList<String> sgList = new ArrayList<>();sgList.add("吕布");sgList.add("周瑜");ArrayList<String> xaList = new ArrayList<>();xaList.add("令狐冲");xaList.add("林平之");ArrayList<String> sdList = new ArrayList<>();sdList.add("郭靖");sdList.add("杨过");LinkedHashMap<String, ArrayList<String>> hashMap = new LinkedHashMap<>();hashMap.put("三国演义", sgList);hashMap.put("笑傲江湖", xaList);hashMap.put("神雕侠侣", sdList);Set<String> keySet = hashMap.keySet();for (String s : keySet) {System.out.println(s);ArrayList<String> list = hashMap.get(s);for (String s1 : list) {System.out.println("\t" + s1);}System.out.println();}
}

ArrayList嵌套HashMap

public static void main(String[] args) {/*周瑜-- - 小乔吕布-- - 貂蝉郭靖-- - 黄蓉杨过-- - 小龙女令狐冲-- - 任盈盈林平之-- - 岳灵珊*/HashMap<String, String> sgMap = new HashMap<>();sgMap.put("周瑜","小乔");sgMap.put("吕布", "貂蝉");HashMap<String, String> sdMap = new HashMap<>();sdMap.put("郭靖", "黄蓉");sdMap.put("杨过", "小龙女");HashMap<String, String> xaMap = new HashMap<>();xaMap.put("令狐冲", "任盈盈");xaMap.put("林平之", "岳灵珊");ArrayList<HashMap<String, String>> maxList = new ArrayList<>();maxList.add(sgMap);maxList.add(sdMap);maxList.add(xaMap);for (HashMap<String, String> minMap : maxList) {Set<Map.Entry<String, String>> entries = minMap.entrySet();for (Map.Entry<String, String> entry : entries) {String key = entry.getKey();String value = entry.getValue();System.out.println(key+"------"+value);}System.out.println();}
}
  相关解决方案