大数据Java基础DAY21——集合完结(Map接口,HashMap,Linked Hash Map,TreeMap,Collections类)

Posted 16年义务教育

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据Java基础DAY21——集合完结(Map接口,HashMap,Linked Hash Map,TreeMap,Collections类)相关的知识,希望对你有一定的参考价值。

目录

Map接口

Map接口概述

Map接口和Collection接口的不同     ( Collection接口 )

Map接口成员方法

添加功能   

删除功能

判断功能

获取功能

长度功能

Map集合遍历

方式1:根据键找值

方式2:根据键值对对象找键和值

HashMap类

HashMap类概述

HashMap案例

LinkedHashMap类

TreeMap类

TreeMap类概述

TreeMap案例

Map集合练习案例

HashMap与Hash table的区别

Collections类

Collections类概述

Collections类和Collection的区别

Collections成员方法

Collections中的方法能线程不安全的集合变成安全的


Map接口

Map接口概述

a.将键映射到值的对象

b.一个映射不能包含重复的键

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

Map接口和Collection接口的不同     ( Collection接口 )

a.Map是双列的,Collection是单列的

b.Map的键唯一,Collection的子体系Set是唯一的

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

Map接口成员方法

添加功能   

V put(K key,V value)    将指定的值与该映射中的指定键相关联

import java.util.HashMap;
import java.util.Map;

public class MapTest1 
    public static void main(String[] args) 
        //Map是一个接口,不能实例化,借助子类HashMap来实例化
        Map<String, String> map = new HashMap<>();

        //V put(K key,V value) 将指定的值与该映射中的指定键相关联
        map.put("充电器","手机");
        map.put("电脑","鼠标");
        System.out.println(map.put("电脑","键盘"));  //如果插入的键一样,值会被覆盖,返回的是被覆盖的值
        System.out.println(map);
    

删除功能

V remove(Object key)      如果存在(从可选操作),从该Map中删除一个键的映射

map.remove("电脑");

void clear()      从该Map中删除所有的映射(可选操纵)

map.clear();

判断功能

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

 //boolean containsKey(Object key)  如果此映射包含指定键的映射,则返回true
        System.out.println(map);
        System.out.println(map.containsKey("充电器"));

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

map.containsValue("手机")

boolean isEmpty()   如果此Map不包含键值映射,则返回true

map.isEmpty();//判断是否有键值对,有返回true,无false

获取功能

V get(Object key)   返回指定键所映射的值,或null如果此映射包含该键的映射

System.out.println(map.get("充电器"));

Set<K> keySet()   返回此Map中包含的键的Set试图

Set<String> set=map.keySet();
        //遍历
        for (String s:set)
            System.out.println(s);
        

Collection<V> values()   返回此Map中包含的值的Collection视图

 //Collection<V> values() 返回此Map中包含的值的Collection视图
        Collection<String> value =map.values();
        for (String s :value)
            System.out.println(s);
        

Set<Map.Entry<K,V>> entrySet()   获取Map中所有的元素,元素的类组成是由一个键和一个值组成

 //Set<Map.Entry<K,V>> entrySet() 获取Map中所有的元素,元素的类组成是由一个键和一个值组成
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> s :entries)
            System.out.println(s);
        

长度功能

int size()   返回此Map中键值映射的数量

        int size = map.size();
        System.out.println(size);  //结果为2,取决于里面有多少个键值对

Map集合遍历

方式1:根据键找值

获取所有键的集合

遍历键的集合,获取到每一个键

根据键找值

例:

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapTest2 
    public static void main(String[] args) 
        //创建集合对象
        Map<Integer, String> map = new HashMap<>();

        //向集合添加元素
        map.put(11,"qew");
        map.put(23,"qew");
        map.put(33,"sfs");
        map.put(22,"asf");
        
        //遍历
        Set<Integer> set = map.keySet(); //获取到每一个键
        for (Integer s:set)
            String s1 = map.get(s);  //获取到每一个键对应的值
            System.out.println(s+":"+s1);
        
    

方式2:根据键值对对象找键和值

获取所有键值对对象的集合

遍历键值对对象的集合,获取到每一个键值对对象

根据键值对对象找键和值

       //创建集合对象
       Map<Integer, String> map = new HashMap<>();

       //向集合添加元素
        map.put(4,"rte");
        map.put(23,"d234");
        map.put(5,"e121");
        map.put(75,"qee");
        map.put(22,"fa");

        //遍历
        Set<Map.Entry<Integer, String>> entries = map.entrySet();  //获取到键值对集合
        for (Map.Entry<Integer, String> s:entries)
            Integer key = s.getKey();     //获取到键值对对应的键
            String value = s.getValue();  //获取到键值对对应的值
            System.out.println(key+":"+value);
        

HashMap类

HashMap类概述

键是哈希表结构,可以保证键的唯一性

HashMap案例

HashMap<String,String>

HashMap<Integer,String>

上面两个跟Map集合中的案例一样,重点说下面的

HashMap<String,Student>

首先封装一个学生类

public class Student 
    private String name;
    private int age;

    public Student() 
    public Student(String name, int age) 
        this.name = name;
        this.age = age;
    

    public String getName() 
        return name;
    
    public int getAge() 
        return age;
    

    public void setName(String name) 
        this.name = name;
    
    public void setAge(int age) 
        this.age = age;
    

    @Override
    public String toString() 
        return "Student" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '';
    

在创建集合添加学生对象测试

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapTest1 
    public static void main(String[] args) 
        //创建集合对象
        HashMap<String, Student> hashMap = new HashMap<>();

        //创建学生对象
        Student s1 =new Student("student1",23);
        Student s2 =new Student("student2",14);
        Student s3 =new Student("student3",17);
        Student s4 =new Student("student4",25);
        Student s5 =new Student("student5",23);

        //向集合添加元素
        hashMap.put("sas",s1);
        hashMap.put("qwe",s2);
        hashMap.put("fsa",s3);
        hashMap.put("ddd",s4);
        hashMap.put("qca",s5);

        //遍历
        Set<Map.Entry<String, Student>> entries = hashMap.entrySet();
        for (Map.Entry<String, Student> s:entries)
            String key = s.getKey();
            Student value = s.getValue();   //也可以调用student中的get方法把名字,年龄获取出来遍历
            System.out.println(key+":"+value);
        
    

HashMap<Student,String>

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapTest2 
    public static void main(String[] args) 
        //创建集合对象
        HashMap<Student, String> hashMap = new HashMap<>();

        //创建学生对象
        Student s1=new Student("qa",23);
        Student s2=new Student("ea",25);
        Student s3=new Student("fa",22);
        Student s4=new Student("da",15);
        Student s5=new Student("qa",23);

        //向集合添加元素
        hashMap.put(s1,"111");
        hashMap.put(s2,"222");
        hashMap.put(s3,"333");
        hashMap.put(s4,"444");
        hashMap.put(s5,"555");

        //遍历
        Set<Map.Entry<Student, String>> entries = hashMap.entrySet();
        for (Map.Entry<Student, String> s:entries)
            Student key = s.getKey();
            String value = s.getValue();
            System.out.println(key+":"+value);
        

    

 从输出结果能发现,key有重复的对象,这违背了map中键是唯一的定义,原因是添加元素的put方法的源码涉及到hashCode()方法和equals()方法来判断元素是否重复(在Hash Set类中说过,Set接口 ),而我们创建做为key的自定义Student类中没有重写hashCode()方法和equals()方法,所以只能调用Object类中的equals方法来比较地址值,每一个学生对象都是new出来的,地址值固然不一样。

解决方法:在Student类中重写hashCode()方法和equals()方法

 @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    

    @Override
    public int hashCode() 
        return Objects.hash(name, age);
    

 这样key就不会重复了

LinkedHashMap类

LinkedHashMap类概述

a.继承自HashMap类,实现了Map接口

b.Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。

哈希表保证元素的唯一,保证key是唯一

链表保证有序 (存储和取出的顺序一致)

例:

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class LinkedHashMapTest1 
    public static void main(String[] args) 
        //创建集合对象
        LinkedHashMap<String, String> map = new LinkedHashMap<>();

        //向集合添加元素
        map.put("s1","qqw");
        map.put("s2","q232");
        map.put("s3","q211");
        map.put("s4","d23");
        map.put("s1","dsa");

        //遍历
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> s:entries)
            String key = s.getKey();
            String value = s.getValue();
            System.out.println(key+":"+value);
        

    

 从结果可以看出重复的key的值被覆盖了,并且输出的顺序就是存放的顺序

TreeMap类

TreeMap类概述

键是红黑树结构,可以保证键的排序和唯一性

TreeMap案例

HashMap<String,String>

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapTest1 
    public static void main(String[] args) 
        //创建集合对象
        TreeMap<String, String> map = new TreeMap<>();

        //向集合添加元素
        map.put("HashSet","Set接口");
        map.put("TreeSet","Set接口");
        map.put("LinkedHashSet","Set接口");
        map.put("HashMap","Map接口");
        map.put("HashMap","Map接口");

        //遍历
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> s:entries)
            String key = s.getKey();
            String value = s.getValue();
            System.out.println(key+":"+value);
        
    

可以看出结果去重了,而且按key中的首字母排序,因为无参构造走的是自然排序,String类实现了Comparable接口,重写了ComparaTo方法( TreeSet类中有说过),String中ComparaTo方法比较ASCII码值,所以按首字母排序。

HashMap<Student,String>

方法一:

首先封装一个学生类2,跟学生类1一样的(不加hashCode方法和equals方法)

再创建集合

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapTest2 
    public static void main(String[] args) 
        //创建集合对象
        TreeMap<Student2, String> map = new TreeMap<>();

        //创建学生对象
        Student2 s1 =new Student2("student1",23);
        Student2 s2 =new Student2("student2",22);
        Student2 s3 =new Student2("student3",23);
        Student2 s4 =new Student2("student1",23);
        Student2 s5 =new Student2("student4",20);

        //向集合添加元素
        map.put(s1,"q111");
        map.put(s2,"w111");
        map.put(s3,"e111");
        map.put(s4,"q111");
        map.put(s5,"t111");

        //遍历
        Set<Map.Entry<Student2, String>> entries = map.entrySet();
        for (Map.Entry<Student2, String> s:entries)
            Student2 key = s.getKey();
            String value = s.getValue();
            System.out.println(key+":"+value);
        
    

然后到这一步你会报错,因为这里走的还是无参构造,自然排序,所创建的Stuent2类没有实现Comparable接口,而自然排序这个接口中有一个向下转型,所以会类型转换异常报错(具体跟TreeSet类中一 样  Set接口 )

解决方法:创建的Student2类需实现Comparable接口,并重写接口的ComparaTo方法,在其中自定义排序方法

public class Student2 implements Comparable<Student2> 
    private String name;
    private int age;

    public Student2() 
    

    public Student2(String name, int age) 
        this.name = name;
        this.age = age;
    

    public String getName() 
        return name;
    

    public int getAge() 
        return age;
    

    public void setName(String name) 
        this.name = name;
    

    public void setAge(int age) 
        this.age = age;
    

    @Override
    public String toString() 
        return "Student" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '';
    

    @Override
    public int compareTo(Student2 o) 
        //比较年龄是否一样
        int i1=o.age-this.age;
        //年龄一样,姓名不一定一样
        int i2= i1==0 ? o.name.compareTo(this.name):i1;
        return i2;
    

可以看出结果去重且按自定义方法排序(按年龄) 

方法二:

当然,如果你不想改动学生类,那就走有参构造方法,也就是比较器排序

此时学生类是最初的封装状态,不需要修改,只需要在创建对象时修改就可以了,这里采用匿名内部类的方式,直接在创建对象时实现Comparato接口。

 //创建集合对象
        TreeMap<Student2, String> map = new TreeMap<>(new Comparator<Student2>()    //匿名内部类
            @Override
            public int compare(Student2 o1, Student2 o2) 
                //比较年龄是否一样
                int i1 = o1.getAge() - o2.getAge();
                //年龄一样,姓名不一定一样
                int i2 = i1 == 0 ? o1.getName().compareTo(o2.getName()) : i1;
                return i2;
            
        );

Map集合练习案例

例1:"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class MapTest4 
    public static void main(String[] args) 
        //创建字符串对象
        String s="aababcabcdabcde";
        //创建集合对象
        TreeMap<Character, Integer> map = new TreeMap<>();
        char[] chars = s.toCharArray(); //转成字符数组
        //遍历字符数组
        for (Character c : chars) 
            Integer integer = map.get(c); //用每一个字符当作键去找值

            if (integer == null)   //如果输出值为null,表示集合中没有这个键,添加这个键并赋值1;
                map.put(c, 1);
             else    //如果输出不为null,表示集合中有这个键,赋值返回的值value+1,返回覆盖到集合中
                integer++;
                map.put(c, integer);
            
        
        //遍历集合
        Set<Map.Entry<Character, Integer>> entries = map.entrySet();
        for (Map.Entry<Character, Integer> e:entries)
            Character key = e.getKey();
            Integer value = e.getValue();
            System.out.print(key+"("+value+")");
        
    

例2:ArrayList集合嵌套HashMap集合

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapTest5 
    public static void main(String[] args) 
        //创建ArrayList集合对象
        ArrayList<HashMap<String, String>> list = new ArrayList<>();
        
        //创建2个HashMap集合,并添加元素
        HashMap<String, String> map1 = new HashMap<>();
        map1.put("user1","qwq");
        map1.put("user2","q33q");
        HashMap<String, String> map2 = new HashMap<>();
        map2.put("user3","q3we");
        map2.put("user4","aa");
        
        //把HashMap集合添加进入ArrayList集合
        list.add(map1);
        list.add(map2);
        
        //遍历ArrayList集合
        for (HashMap<String, String> s:list)
            //遍历HashMap集合
            Set<Map.Entry<String, String>> entries = s.entrySet();
            for (Map.Entry<String, String> m:entries)
                String key = m.getKey();
                String value = m.getValue();
                System.out.println(key+":"+value);
            
        
    

HashMap与Hash table的区别

a.Hash Map和Hash table它们存储的都是一个个的键值对

b.Hash Map中允许key,value为null,而Hash table不允许

c.Hashtable是线程安全的,HashMap是不安全的

Collections类

Collections类概述

针对集合操作 的工具类

Collections类和Collection的区别

a.Collection是单列集合的顶层接口,有两大子类接口:List接口和Set接口

b.Collections是一个针对于集合操作的工具类,可以对集合进行排序,还有查找(二分查找)

Collections成员方法

public static <T> void sort(List<T> list)   集合排序

import java.util.ArrayList;
import java.util.Collections;

public class CollectionsTest1 
    public static void main(String[] args) 
        //创建集合对象
        ArrayList<Integer> list = new ArrayList<>();
        //向集合添加元素
        list.add(54);
        list.add(23);
        list.add(123);
        list.add(42);
        list.add(32);
        list.add(24);

        //public static <T> void sort(List<T> list) 排序
        System.out.println("原集合:"+list);
        Collections.sort(list);
        System.out.println("排序后:"+list);
    

public static <T> int binarySearch(List<?> list,T key)   二分查找,返回索引

        System.out.println("原集合:"+list);
        int i = Collections.binarySearch(list, 123);
        System.out.println(i);

public static <T> T max(Collection<?> coll)      集合中最大值

        Integer max = Collections.max(list);
        System.out.println(max);  //123

public static void reverse(List<?> list)    反转

        System.out.println("原集合:"+list);
        Collections.reverse(list);
        System.out.println("反转后:"+list);

public static void shuffle(List<?> list)     随机置换(随机排序)

        System.out.println("原集合:"+list);
        Collections.shuffle(list);
        System.out.println("随机置换后:"+list);

Collections中的方法能线程不安全的集合变成安全的

例: static <T> List<T> synchronizedList(List<T> list)    (还有很多,不一一举例了)

         返回由指定列表支持的同步(线程安全)列表。

 List<Integer> list1 = Collections.synchronizedList(list);
        System.out.println(list);
        System.out.println(list1);

 可以看出两个list和list1是一样的,Collections只是给list套了一层,让它变成安全的,在Vector类中说过虽然Vector是安全的,但Collections工具类比它更好。

以上是关于大数据Java基础DAY21——集合完结(Map接口,HashMap,Linked Hash Map,TreeMap,Collections类)的主要内容,如果未能解决你的问题,请参考以下文章

# Day18-Java基础

Day12Java基础学习笔记

JAVA零基础小白学习免费教程day14-Set&HashMap

JAVA零基础小白学习免费教程day14-Set&HashMap

day16 java语言中的----set集合

《java基础知识》Java集合(Map)