Java学习记录 Day15(Set集合、Map集合)

Day 15

2019年5月11日。
这是我学习Java的第十五天。
这一天,我学到了以下的知识。

Set集合

Set,特点为元素唯一,是一个不包含重复元素的Collection(集合)

以下,讲解Set接口下的实现类

  • HashSet
    底层数据结构是哈希表和数组,是元素为链表的数组
    元素唯一,但不有序
    集合元素可以是null
    线程不安全
    构造方法:HashSet()构造一个新的空Set,底层是HashMap,默认初始容量是16,加载银子是0.75

    格式
    HashSet<T> hashSet = new HashSet<>();

    特点
    HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证
    当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
    HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。(Interger类和String类已经重写了这两个方法)
    例如:用HashSet存储Student对象,在Student对象中重写这两个方法(可以用IDEA的快捷键Alt + Insert快速创捷)

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 void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

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

    @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);
    }
}
  • LinkedHashSet
    底层数据结构是哈希表和链表
    链表保证有序,哈希表保证元素唯一
    构造方法:LinkedHashSet()构造一个新的空Set,底层是HashMap,默认初始容量是16,加载银子是0.75

    格式
    LinkedHashSet<T> linkedHashSet = new LinkedHashSet<>();

  • TreeSet
    底层数据结构是二叉树
    能够对元素进行排序
    构造方法:TreeSet()构造一个新的空Set,根据元素的自然顺序进行排序

    格式
    TreeSet<T> treeSet = new TreeSet<>();

    特点
    TreeSet对元素有两种排序方式:分为自然排序(空参构造)和比较器排序(有参构造)

    • 自然排序:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素必须实现Comparable接口,否则无法进行自然排序。而保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0,表示两个元素相等,则不重复存储。
      例如:用TreeSet存储Student对象,在Student对象中重写Comparble接口的CompareTo(T t)方法,根据该方法的返回值的正负0,来进行排序
public class Student implements Comparable<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 void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

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


    @Override
    public int compareTo(Student s) {
        //比较逻辑是按照年龄大小来排序
        int num = this.age - s.age;
        //当年龄相同不能说明他是同一个对象,还得比较姓名
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        //if(num==0){
        //    num=this.name.compareTo(s.name);
        //}

        return num2;
    }
}
  • 比较器排序:要求新建一个实现了Comparator接口的比较器类
    例如:以上一个范例的Student对象进行编写,编写一个MyComparator类
public class MyComparator implements Comparator<Student> {
    @Override
    public int compare(Student s1, Student s2) {
        //按照年龄来排
        int num = s1.getAge() - s2.getAge();
        int num2=num==0?s1.getName().compareTo(s2.getName()):num;
        return num2;
    }
}

Map集合

Map,特点可以存储将键映射到值的对象,且一个映射不能包含重复的键,每个键最多只能映射到一个值

首先,讲解Map接口下的方法

  • 添加功能

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

    • void clear()移除所有的键值对元素
    • V remove(Object key)根据键删除键值对元素,并把值返回
  • 判断功能

    • boolean containsKey(Object key)判断集合是否包含指定的键
    • boolean containsValue(Object value)判断集合是否包含指定的值
    • boolean isEmpty()判断集合是否为空
  • 获取功能

    • Set<Map.Entry<K,V>> entrySet()返回一个键值对的Set集合
    • V get(Object key)根据键获取值
    • Set<K> keySet()获取集合中所有键的集合
    • Collection<V> values()获取集合中所有值的集合
  • 长度功能

    • int size()返回集合中的键值对的对数
  • 遍历

    • 获取所有键的集合
      遍历键的集合,获取到每一个键
      根据键找值
    • 获取所有键值对对象的集合
      遍历键值对对象的集合,获取到每一个键值对对象
      根据键值对对象找键和值

    例如:遍历一个存储着 数字(Integer)——字符(String) 对象的Map集合,分别使用两张遍历方式

public class Test{
    public static void main (String[] args) {
        HashMap<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "aaa");
        hashMap.put(2, "bbb");
        hashMap.put(3, "ccc");
        
        //1.通过键的集合来取值
        Set<Integer> integers = hashMap.keySet();
        for (Integer key : integers) {
            System.out.println(key + "===" + hashMap.get(key));
        }
        
        //2.通过键值对来遍历
        //entrySet() 获取键值对 对象 放到Set集合里面去
        Set<Map.Entry<Integer, String>> entries = hashMap.entrySet();
        //K getKey ()
        //返回与此项对应的键。
        //V getValue ()
        //返回与此项对应的值。
        for (Map.Entry<Integer, String> entry : entries) {
            //System.out.println(entry);
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"==="+value);
        }
        
    }
}

之后,讲解Map接口下的实现类

  • HashMap
    允许插入null键 null值,要保证元素的唯一性,也要重写元素里的hashCode()方法和 equals()方法
    格式
    HashMap<K, V> hashMap = new HashMap<>();

  • LinklistedMap
    Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序
    底层的数据结构是链表和哈希表,元素有序,并且唯一
    元素的有序性由链表数据结构保证,唯一性由哈希表数据结构保证
    Map集合的数据结构只和键有关
    格式
    LinkedHashMap<K, V> linkedHashMap = new LinkedHashMap<>();

  • TreeMap
    TreeMap 键不允许插入null
    键的数据结构是红黑树,可保证键的排序和唯一性
    排序分为自然排序和比较器排序
    线程是不安全的,效率比较高
    格式
    TreeMap<K, V> treeMap = new TreeMap<>();

Map集合的经典算法

  • 统计字符出现的个数
    需求:统计字符串中每个字符出现的次数
    aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5) b(4) c(3) d(2) e(1)
    代码如下

      public class Test {
     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<>();
         char ch;
         for (int i = 0; i < str.length() ; i++) {
             int num = 0;
             ch = str.charAt(i);
             for (int j = i; j < str.length(); j++){
                 if (ch == str.charAt(j)){
                     num ++;
                 }
                 hashMap.put(ch,num);
             }
         }
         System.out.println(hashMap);
     }}
    
  • 集合嵌套

    • HashMap 嵌套 ArrayList
public class MyTest {
    public static void main(String[] args) {

        /**
         *
         三国演义
            吕布
            周瑜
         笑傲江湖
            令狐冲
            林平之
         神雕侠侣
            郭靖
            杨过
         */

        //  HashMap 嵌套 ArrayList
        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("杨过");
        sdList.add("尹志平");

        LinkedHashMap<String, ArrayList<String>> maxMap = new LinkedHashMap<>();
        maxMap.put("三国演义", sgList);
        maxMap.put("笑傲江湖", xaList);
        maxMap.put("神雕侠侣", sdList);

        //遍历
        /**
         *
         三国演义
             吕布
             周瑜
         笑傲江湖
             令狐冲
             林平之
         神雕侠侣
             郭靖
             杨过
         */
        Set<String> keySet = maxMap.keySet();
        for (String key : keySet) {
            System.out.println(key);
            ArrayList<String> list = maxMap.get(key);
            for (String s : list) {
                System.out.println("\t"+s);
            }
            System.out.println();
        }


    }
}

  • HashMap 嵌套 HashMap
public class MyTest2 {
    public static void main(String[] args) {

      /* 基础班
            张三 20
            李四 22
        就业班
            王五 21
            赵六 23

            */

        //HashMap 嵌套 HashMap
        HashMap<String, Integer> jc = new HashMap<>();
        jc.put("张三", 20);
        jc.put("李四", 22);


        HashMap<String, Integer> jy = new HashMap<>();
        jy.put("王五", 21);
        jy.put("赵六", 23);

        HashMap<String, HashMap<String, Integer>> maxMap = new HashMap<String, HashMap<String, Integer>>();
        maxMap.put("基础班", jc);
        maxMap.put("就业班", jy);

        //遍历集合
        Set<String> keySet = maxMap.keySet();
        for (String s : keySet) {
            System.out.println(s);
            HashMap<String, Integer> minMap = maxMap.get(s);
            Set<String> minKey = minMap.keySet();
            for (String s1 : minKey) {
                System.out.println("\t" + s1 + "\t" + minMap.get(s1));
            }
            System.out.println();
        }
        System.out.println("------------------------");
        Set<Map.Entry<String, HashMap<String, Integer>>> entries = maxMap.entrySet();
        for (Map.Entry<String, HashMap<String, Integer>> en : entries) {
            String key = en.getKey();
            System.out.println(key);
            HashMap<String, Integer> minMap = en.getValue();
            Set<Map.Entry<String, Integer>> entries1 = minMap.entrySet();
            for (Map.Entry<String, Integer> stringIntegerEntry : entries1) {
                String key1 = stringIntegerEntry.getKey();
                Integer value = stringIntegerEntry.getValue();
                System.out.println("\t"+key1+"  "+value);
            }
            System.out.println();
        }
    }
}

  • ArrayList 嵌套 HashMap
public class MyTest3 {
    public static void main(String[] args) {
        //周瑜-- - 小乔
        //吕布-- - 貂蝉
        //
        //郭靖-- - 黄蓉
        //杨过-- - 小龙女
        //
        //令狐冲-- - 任盈盈
        //林平之-- - 岳灵珊

        //ArrayList 嵌套 HashMap
        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> map : maxList) {
            Set<Map.Entry<String, String>> entries = map.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                System.out.println(key + "-----" + value);
            }
            System.out.println();
        }

    }
}

  • 斗地主 发牌和洗牌
    需求:模拟斗地主洗牌和发牌,牌没有排序
    代码如下
public class MyTest2 {
    public static void main(String[] args) {
        //得有一副牌
        HashMap<ArrayList<Integer>,String> pokerBox = new HashMap<>();
        ArrayList<Integer> arrayList = new ArrayList<>();
        //生成54张牌放到牌盒里面
        String[] colors = {"♠", "♥", "♦", "♣"};
        String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        int index = 0;
        for (String color : colors) {
            for (String num : nums) {
                arrayList.add(index);
                pokerBox.put(arrayList,color.concat(num));
                index ++;
            }
        }
        //手动添加大小王
        arrayList.add(52);
        pokerBox.put(arrayList,"★");
        arrayList.add(53);
        pokerBox.put(arrayList,"☆");
        //洗牌
        Collections.shuffle(arrayList);
        Collections.shuffle(arrayList);
        Collections.shuffle(arrayList);
        System.out.println(arrayList);
        //发牌
        TreeSet<Integer> 高进 = new TreeSet<>();
        TreeSet<Integer> 刀仔 = new TreeSet<>();
        TreeSet<Integer> 星仔 = new TreeSet<>();
        TreeSet<Integer> 底牌 = new TreeSet<>();
        // 高进 = (ArrayList<String>) pokerBox.subList(0,17);
        // 高进 0  3 6 9
        //刀仔 1 4 7 10
        //  星仔 2 5 8 11
        for (int i = 0; i < pokerBox.size(); i++) {
            if (i >= pokerBox.size() - 3) {
                底牌.add(arrayList.get(i));
            } else if (i % 3 == 0) {
                高进.add(arrayList.get(i));
            } else if (i % 3 == 1) {
                刀仔.add(arrayList.get(i));
            } else {
                星仔.add(arrayList.get(i));
            }
        }

        //看牌
        lookPoker("高进",高进,pokerBox);
        lookPoker("刀仔",刀仔,pokerBox);
        lookPoker("星仔",星仔,pokerBox);
        lookPoker("底牌",底牌,pokerBox);


    }

    private static void lookPoker(String name, TreeSet<Integer> list,HashMap<ArrayList<Integer>,String> Box) {
        System.out.println(name);
        for (Integer integer : list) {
            System.out.print(integer  + "   ");
        }
        System.out.println("\n");
        
    }
}

Map和Collection的区别

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

猜你喜欢

转载自blog.csdn.net/qq_41151659/article/details/90116134