Map

  • 将键映射到值的对象
  • 一个映射不能包含重复的键
  • 每个键最多只能映射到一个值

Map 与 Collection 接口的不同

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

Map 方法

  • V put(K key, V value) 添加键和值, 成功返回null, 覆盖重复key值, 则返回被覆盖的Value值
  • V remove(Object key) 通过key删除元素, 删除成功则返回Value值
  • boolean containsKey(Object key) Map 中是否包含Key值
  • boolean containsValue(Object value) Map 中是否包含Value值
  • boolean isEmpty() Map 是否为空
  • clear() 清空Map
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class Demo1_Map {
    public static void main(String[] args) {
//        Demo1();
        Map<String, Integer> hashMap = new HashMap<>();
        hashMap.put("小明", 18);
        hashMap.put("小红", 19);
        hashMap.put("小王", 20);
        System.out.println(hashMap);
        Integer i =  hashMap.remove("小王");
        System.out.println(i);
        System.out.println(hashMap);

        System.out.println(hashMap.containsKey("小明"));
        System.out.println(hashMap.containsValue(19));
        System.out.println(hashMap.isEmpty());

        Collection<Integer> v = hashMap.values();
        System.out.println(v);
        hashMap.clear();
        System.out.println(hashMap.size());

    }

    private static void Demo1() {
        Map<String,Integer> map = new HashMap<>();
        Integer i1 = map.put("s1",12);
        Integer i2 = map.put("s2",22);
        Integer i3 = map.put("s3",33);
        Integer i4 = map.put("s3",34);
        Integer i5 = map.put("s5",35);
        Integer i6 = map.put("s6",35);
        System.out.println(map);
        System.out.println(i4);
        System.out.println(i5);
        System.out.println(i6);
    }
}

Map 根据键获取值

import java.util.HashMap;

public class Demo2_Iterator {
    public static void main(String[] args) {
        HashMap<String, Integer> hashMap = new HashMap<>();

        hashMap.put("a", 100);
        hashMap.put("b",90);
        hashMap.put("c",98);

        for(String s:hashMap.keySet()){
            System.out.println(s + "="+ hashMap.get(s));
        }
    }
}

Map 的键值对, 来获取Map中的Key 与 Value

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

public class Demo3_Iterator {
    public static void main(String[] args) {
        HashMap<String, Integer> hashMap = new HashMap<>();

        hashMap.put("a", 90);
        hashMap.put("b",95);
        hashMap.put("c",98);

        for(Map.Entry<String,Integer> single: hashMap.entrySet()){
            System.out.println(single.getKey() + " "+ single.getValue());
        }
    }
}

HashMap 存入Student类和String时, 重写 hashCode 和 equals方法

import lombok.Getter;
import lombok.Setter;

import java.util.Objects;

public class Student {
    public Student(){}
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    @Getter
    @Setter
    private String name;

    @Getter
    @Setter
    private int age;

    @Override
    public String toString() {
        return "Student "+this.name+this.age;
    }

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

    @Override
    public boolean equals(Object obj) {
        Student s = (Student) obj;
        return this.name == s.name && this.age == s.age;
    }
}
import com.lizicai.bean.Student;

import java.util.HashMap;

public class Demo4_HashMap {
    public static void main(String[] args) {
        HashMap<Student, String> hashMap = new HashMap<>();
        hashMap.put(new Student("小明",23), "上海");
        hashMap.put(new Student("小明",23), "北京");
        hashMap.put(new Student("小王",26), "北京");
        hashMap.put(new Student("莱昂纳多",28), "美国");
        System.out.println(hashMap);
    }
}

LinkedHashMap

import java.util.LinkedHashMap;

public class Demo5_LinkedHashMap {
    public static void main(String[] args) {
        LinkedHashMap<String,Integer> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("a", 20);
        linkedHashMap.put("b", 20);
        linkedHashMap.put("c", 20);
        System.out.println(linkedHashMap);
    }
}

TreeMap 必须实现 Comparable 接口, 2种方式

方式一在bean类中实现Comparable 接口

import lombok.Getter;
import lombok.Setter;

import java.util.Objects;

public class Student implements Comparable<Student>{
    public Student(){}
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    @Getter
    @Setter
    private String name;

    @Getter
    @Setter
    private int age;

    @Override
    public String toString() {
        return "Student "+this.name+this.age;
    }

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

    @Override
    public boolean equals(Object obj) {
        Student s = (Student) obj;
        return this.name == s.name && this.age == s.age;
    }

    @Override
    public int compareTo(Student o) {
        int numName = this.name.compareTo(o.name);
        int numAge = numName == 0 ? this.age-o.age : numName;
        return numAge;
    }
}
public class Demo6_TreeMap {
    public static void main(String[] args) {
//        Demo1();
        TreeMap<Student, String> treeMap = new TreeMap<>();
        treeMap.put(new Student("ab",23), "上海");
        treeMap.put(new Student("ab",23), "北京");
        treeMap.put(new Student("ac",26), "北京");
        treeMap.put(new Student("abc",28), "美国");

        System.out.println(treeMap);

    }
}

方式二, 在创建TreeMap时实现 Comparator 接口

public static void main(String[] args) {
    TreeMap<Student, String> treeMap = new TreeMap<>(new Comparator<Student>() {
        @Override
        public int compare(Student o1, Student o2) {
            int numName = o1.getName().compareTo(o2.getName());
            int numAge = numName == 0 ? o1.getAge()-o2.getAge() : numName;
            return numAge;
        }
    });
    treeMap.put(new Student("ab",23), "上海");
    treeMap.put(new Student("ab",23), "北京");
    treeMap.put(new Student("ac",26), "北京");
    treeMap.put(new Student("abc",28), "美国");

    System.out.println(treeMap);

}

练习, 字符串 aaabbbccccfgkj 统计字母出现次数

  • 字母在Map里Key 没有, 由存入key,1, 有则存key, value+1
import java.util.HashMap;
import java.util.Map;

public class Demo7_HashMap {
    public static void main(String[] args) {
        HashMap<Character, Integer> hashMap = new HashMap<>();
        String str = "aaabbbbccccd";
        char[] cArray = str.toCharArray();
        for(char c : cArray){
            if( ! hashMap.containsKey(c)){
                hashMap.put(c,1);
            } else {
                hashMap.put(c, hashMap.get(c)+1);
            }
        }
        for(Map.Entry<Character,Integer> ci:hashMap.entrySet()){
            System.out.println(ci.getKey() + "=" + ci.getValue() );
        }
    }
}

练习 HashMap 嵌套 HashMap

import lombok.Getter;
import lombok.Setter;

import java.util.Objects;

public class Student implements Comparable<Student>{
    public Student(){}
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    @Getter
    @Setter
    private String name;

    @Getter
    @Setter
    private int age;

    @Override
    public String toString() {
        return "Student "+this.name+this.age;
    }

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

    @Override
    public boolean equals(Object obj) {
        Student s = (Student) obj;
        return this.name == s.name && this.age == s.age;
    }
import com.lizicai.bean.Student;

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

public class Demo8_HashMapHashMap {
    public static void main(String[] args) {
        HashMap<Student, String> hashMap1 = new HashMap<>();
        hashMap1.put(new Student("小明",23), "上海");
        hashMap1.put(new Student("小王",26), "北京");
        hashMap1.put(new Student("莱昂纳多",28), "美国");
        HashMap<Student, String> hashMap2 = new HashMap<>();
        hashMap2.put(new Student("小明",23), "上海");
        hashMap2.put(new Student("小王",26), "北京");
        hashMap2.put(new Student("莱昂纳多",29), "美国");
        HashMap<HashMap<Student,String>,String > hashMap = new HashMap<>();
        hashMap.put(hashMap1,"班级1");
        hashMap.put(hashMap2,"班级2");
        for(Map.Entry<HashMap<Student,String>, String> HH : hashMap.entrySet()){
            for(Map.Entry<Student,String> HHS : HH.getKey().entrySet()){
                System.out.println(HHS.getKey() + HHS.getValue()+HH.getValue());
            }
        }
        System.out.println(hashMap);
    }
}

HashMap 和 Hashtable 区别

共同点

  • 都是双链集合

区别

  • HashMap 是线程不安全的, 效率高JDK 1.2 版本
  • Hashtable 是线程安全的, 效率低, JDK 1.0 版本
  • HashMap 可以存储null 键 和 null 值
  • Hashtable 不可以存储null 键 及 null 值
import java.util.HashMap;
import java.util.Hashtable;

public class Demo9_HashMapHashtable {
    public static void main(String[] args) {
        HashMap<String, Integer> hashMap = new HashMap<>();
        hashMap.put(null, 10);
        hashMap.put("a", null);
        System.out.println(hashMap);

        Hashtable<String, Integer> hashtable = new Hashtable<>();
        hashtable.put(null, 10);
        hashtable.put("a", null);
        System.out.println(hashtable);
    }
}

Collections 中的方法

  • static <T extends Comparable<? super T» void sort(List list) 排序
  • static int binarySearch(List<? extends Comparable<? super T» list, T key) 二分查找
  • static <T extends Object & Comparable<? super T» T max(Collection<? extends T> coll) 返回最大值
  • static void reverse(List list) 反转列表
  • static void shuffle(List list) list 序列洗牌
private static void Demo5() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("d");
    arrayList.add("a");
    arrayList.add("a");
    arrayList.add("b");
    arrayList.add("c");
    arrayList.add("f");
    System.out.println(arrayList);
    Collections.shuffle(arrayList);
    System.out.println(arrayList);
}

private static void Demo4() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("d");
    arrayList.add("a");
    arrayList.add("a");
    arrayList.add("b");
    arrayList.add("c");
    arrayList.add("f");
    System.out.println(arrayList);
    Collections.reverse(arrayList);
    System.out.println(arrayList);
}

private static void Demo3() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("d");
    arrayList.add("a");
    arrayList.add("a");
    arrayList.add("b");
    arrayList.add("c");
    arrayList.add("f");
    String max = Collections.max(arrayList);
    System.out.println(max);
}

private static void Demo2() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("d");
    arrayList.add("a");
    arrayList.add("a");
    arrayList.add("b");
    arrayList.add("c");
    arrayList.add("a");
    Collections.sort(arrayList);
    System.out.println(arrayList);
    int index = Collections.binarySearch(arrayList, "b");
    System.out.println(index);
    System.out.println(Collections.binarySearch(arrayList,"o"));
}

private static void Demo1() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("d");
    arrayList.add("a");
    arrayList.add("a");
    arrayList.add("b");
    arrayList.add("c");
    arrayList.add("a");
    System.out.println(arrayList);
    Collections.sort(arrayList);
    System.out.println(arrayList);
}

练习, 54 张牌, 每人17张, 剩下3张, 打印每个人牌和底牌

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

public class Demo2_Collections {
    public static void main(String[] args) {
        String[] nu = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
        String[] color = { "♠️",  "♥️", "♦️",  "♣️"};
        ArrayList<String> arrayList = new ArrayList<>();
        for(String nuStr : nu){
            for(String  colorStr : color){
                arrayList.add(nuStr + colorStr);
            }
        }
        arrayList.add("Big King");
        arrayList.add("Small King");
        for(int i=0;i<3;i++){
            Collections.shuffle(arrayList);
        }
        System.out.println(arrayList);
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        ArrayList<String> list3 = new ArrayList<>();
        ArrayList<String> list4 = new ArrayList<>();
        Scanner sc = new Scanner(System.in);
        for(int i=0;i<53;i++){
            if(i >= 50 ){
                list4.add(arrayList.get(i));
            }
            else if( i % 3 == 0){
                list1.add(arrayList.get(i));
            } else if( i % 3 == 1) {
                list2.add(arrayList.get(i));
            } else if( i % 3 ==2 ){
                list3.add(arrayList.get(i));
            }
        }
        System.out.println(list4);
        System.out.println(list1);
        System.out.println(list2);
        System.out.println(list3);
    }
}

练习使用 HashMap 模拟一副牌

  • 用HashMap 的 Key 生成arraylist来洗牌
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeMap;

public class Demo3_Collections {
    public static void main(String[] args) {
        HashMap<Integer, String> poker = new HashMap<>();
        String[] nu = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A","2"};
        String[] color = { "♠️",  "♥️", "♦️",  "♣️"};
        int count = 0;
        ArrayList<Integer> pokerIndex = new ArrayList<>();
        for(String nuStr : nu){
            for(String  colorStr : color){
                poker.put(count, (colorStr + nuStr));
                pokerIndex.add(count);
                count++;
            }
        }
        poker.put(count, "Small King");
        pokerIndex.add(count);
        count++;
        poker.put(count, "Big King");
        pokerIndex.add(count);

        TreeMap<Integer, String> gaojin = new TreeMap<>();
        TreeMap<Integer, String> jp = new TreeMap<>();
        TreeMap<Integer, String> tiger = new TreeMap<>();
        TreeMap<Integer, String> dipai = new TreeMap<>();

        System.out.println(pokerIndex.size());
        Collections.shuffle(pokerIndex);
        System.out.println(pokerIndex);

        for(int i=0;i< pokerIndex.size(); i++){
            int index = pokerIndex.get(i);
            if(i > 50){
                dipai.put( index  , poker.get( index));
            } else if ( i % 3 == 0){
                gaojin.put( index, poker.get(index ));
            } else if (i % 3 == 1){
                jp.put( index , poker.get( index ));
            } else if (i % 3 == 2){
                tiger.put( index, poker.get( index ));
            }
        }
        System.out.println(gaojin);
        System.out.println(jp);
        System.out.println(tiger);
        System.out.println(dipai);

    }
}

? Super E 情况

  • TreeSet TreeMap 会调用
import lombok.Getter;
import lombok.Setter;

import java.util.Objects;

public class Student implements Comparable<Student>{
    public Student(){}
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    @Getter
    @Setter
    private String name;

    @Getter
    @Setter
    private int age;

    @Override
    public String toString() {
        return "Student "+this.name+this.age;
    }

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

    @Override
    public boolean equals(Object obj) {
        Student s = (Student) obj;
        return this.name == s.name && this.age == s.age;
    }

    @Override
    public int compareTo(Student o) {
        int numName = this.name.compareTo(o.name);
        int numAge = numName == 0 ? this.age-o.age : numName;
        return numAge;
    }
}
public class BaseStudent extends Student{
    public BaseStudent(){}
    public BaseStudent(String name, int age){
        super(name, age);
    }
}
import com.lizicai.bean.BaseStudent;
import com.lizicai.bean.Student;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

public class Demo4_Generic {
    public static void main(String[] args) {
//        Demo1();
        TreeSet<Student> treeSet = new TreeSet<>(new CompareByAge());
        treeSet.add(new Student("小明",22));
        treeSet.add(new Student("小红",22));
        treeSet.add(new Student("小王",22));
        System.out.println(treeSet);


        TreeSet<BaseStudent> treeSet2 = new TreeSet<>(new CompareByAge());
        treeSet2.add(new BaseStudent("小明",22));
        treeSet2.add(new BaseStudent("小红",22));
        treeSet2.add(new BaseStudent("小王",22));
        System.out.println(treeSet2);

    }

    private static void Demo1() {
        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(new Student("小明",22));
        arrayList.add(new Student("小红",22));
        arrayList.add(new Student("小王",22));

        ArrayList<BaseStudent> arrayList2 = new ArrayList<>();
        arrayList2.add(new BaseStudent("小明",22));
        arrayList2.add(new BaseStudent("小红",22));
        arrayList2.add(new BaseStudent("小王",22));

        arrayList.addAll(arrayList2);
        System.out.println(arrayList);
    }
}

class CompareByAge implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        int num = o1.getAge() - o2.getAge();
        int numName = num == 0 ? o1.getName().compareTo(o2.getName()): num;
        return numName;
    }
}

Collection

List 存取有序, 有索引, 可重复

  • ArrayList
    • 底层数组实现的, 线程不安全, 查找修改快, 增删慢
  • LinkedList
    • 底层是链表实现的, 线程不安全, 查找慢, 增删快
  • Vetor
    • 底层数组实现的, 线程安全, 查找修改增删都慢

如果查找修改多用ArrayList, 增和删多用LinkedList, 如果都多用ArrayList

Set 存取无序, 无索引, 不可重复

  • HashSet
    • 底层哈希算法实现的
  • LinkedHashSet
    • 底层是链表, 但是也可以保证元素唯一, 和HashSet 原理一样
  • TreeSet
    • 底层是二叉树实现

开发的时候不需要对存储的元素排序, 大多用HashSet TreeSet 比较的2种方式要记住

Map 存取

  • HashMap 底层哈希算法, 针对键的
    • LinkedHashMap 底层是链表
  • TreeMap 底层是二叉树实现

双链集合优先考虑TreeMap