【JavaSE】集合框架3[Map接口、Collection工具类]

① Map集合

特点: 存储一对数据 (Key-Value),无序, 无下标, 键值不能重复, 值可以重复

方法说明
V put(K key, V value)将对象存入到集合当中,关联键值,key重复则覆盖原值
Object get(Object ket)根据键值取得对应的值
Sey<K> keySet()返回所有的key值的Set集合
Collection<V> values()返回所有value值的Collection集合
Set<Map.Entry<K,V>> entrySet()返回键值匹配的Set集合
boolean containsKey(Object key)判断集合中是否包含键值
boolean containsValue(Object value)判断集合中是否包含该value值
default boolean replace(K key,V oldValue, V newValue)指定键值替换value值

在这里插入图片描述

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
 * Map接口的使用
 * 特点
 * 1.存储的是键值对key-value
 * 2.键值key不能重复,value值可以重复
 * 3.无序
 */
public class MapSimple {
    public static void main(String[] args) {
        //创建Map集合
        Map<String,String> map = new HashMap<>();

        //1.添加元素
        map.put("cn","中国");
        map.put("uk","英国");
        map.put("usa","美国");
        //map.put("cn","ZhongGuo");   //键值相同时,后添加的数据会把之前添加的数据顶掉

        System.out.println("元素个数:" + map.size());   //元素个数:3
        System.out.println(map.toString());   //{usa=美国, uk=英国, cn=中国}   {usa=美国, uk=英国, cn=ZhongGuo}

        //2.删除元素  .remove(K key)  .remove(K key,V value)

        //3.遍历
        //3.1 使用keySet()遍历  返回值是所有key的Set集合
        // 增强for
        for (String k : map.keySet()) {
            System.out.println("key:" + k + " value:" + map.get(k));
        }
        //迭代器--推荐使用增强for
        Iterator<String> it = map.keySet().iterator();
        while(it.hasNext()){
            String key = it.next();
            System.out.println("key--" + key + " value--" + map.get(key));
        }


        //3.2 使用entrySet()方法遍历--效率相对较高
        Set<Map.Entry<String, String>> entries = map.entrySet();
        // 增强for
        for (Map.Entry<String, String> entry : entries) {
            System.out.println("key_" + entry.getKey() + " value_" + entry.getValue());
        }

        //4.判断
        System.out.println(map.containsKey("uk"));   //true
        System.out.println(map.containsValue("日本"));   //false
    }
}

- Map集合的实现类

HashMap:

  • JDK1.2版本实现,线程不安全,运行效率快
  • 允许使用null作为key或是value
  • 默认容量16,默认加载因子0.75
  • 方法与Map接口中的方法一样

HashTable:

  • JDK1.0提供,线程安全,运行效率慢
  • 不允许null作为key或value

Properties:

  • HashTable的子类
  • 要求key和value都是String
  • 通常用于配置文件的读取

TreeMap:

  • 实现了SortedMap接口(是Map的子接口)
  • 可以对Key进行自动排序

- HashMap的使用

HashMap:

  • JDK1.2版本实现,线程不安全,运行效率快
  • 允许使用null作为key或是value
  • 默认容量16,默认加载因子0.75
  • 方法与Map接口中的方法一样
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * HashMap的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 使用key的hashcode()以及equals()的返回值作为存储去重的依据
 */
public class HashMapTest1 {
    public static void main(String[] args) {
        //创建聚合K,V
        HashMap<Student,String> students = new HashMap<>();

        //1.添加元素
        Student s1 = new Student("iFinder",167);
        Student s2 = new Student("Nancy",123);
        Student s3 = new Student("BobJoy",213);
        Student s4 = new Student("JackyChan",254);
        students.put(s1,"云南");
        students.put(s2,"北京");
        students.put(s3,"美国");
        students.put(s4,"英国");
        //相同键值,不同value,会把旧的value顶掉
        students.put(new Student("iFinder",167),"云南");  //如果不重写hashCode(),equals()方法,则默认会视为不同对象
        //重写方法后,作为新建对象的参数传入无法成为新的集合元素

        System.out.println("元素个数:" + students.size());
        System.out.println(students.toString());

        //2.删除 .remove(K k)  .remove(K k,V value)

        //3.遍历
        //3.1使用kekSet()遍历
        Set<Student> stuSet = students.keySet();
        for(Student stu:stuSet){
            System.out.println("key-" + stu.toString() + " value-" + students.get(stu));
        }

        //3.2使用entrySet()遍历
        for(Map.Entry<Student,String> entry:students.entrySet()){
            System.out.println("key: " + entry.getKey() + " value: " + entry.getValue());
        }

        //4.判断 .containsKey()  .containsValue()
        //在重写hashcode()方法和equals()方法之后可以将新建的对象作为参数传入实现判断
    }
}

class Student{
    private String name;
    private int stuID;
    //无参构造
    public Student() {
    }
    //有参构造
    public Student(String name, int stuID) {...}
    public String getName() {...}
    public void setName(String name) {...}
    public int getStuID() {...}
    public void setStuID(int stuID) {...}

    @Override
    public String toString() {
        return "name-" + name + " stuID-" + stuID;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        Student student = (Student) o;
        return stuID == student.stuID && Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, stuID);
    }
}

- HashMap源码分析

属性

  • 初始容量: DEFAULT_INITIAL_CAPACITY 1<<4 (16)
  • 最大容量: MAXMUM_CAPACITY 1<<30
  • 加载因子: DEFAULT_LOAD_FACTOR 0.75f (元素数量到达百分之75,开始扩容)
  • 树因子: TREEIFY_THRESHOLO 8(在链表长度大于8,数组长度大于等于64时,将链表改变成红黑树结构)
  • 链表因子:UNTREEIFY_THRESHOLO 6(当红黑树元素小于6,调整为链表)
  • 数组树因子:MIN_TREEIFT_CAPACITY 64
  • transient Node<K,V,> table 哈希表中的数组
  • size 元素的个数

构造方法

  • 刚创建hashMap之后,没有赋值之前 table = null , size = 0.
    添加第一个元素的时候size才为16(为了节省空间)

public V put(K key, V value)方法

  • return putVal(hash(key), key, value, false, true)
  • hash(), 用来产生key的hash值
  • 当元素个数大于阈值(16*0.75=12)时,扩容为原来大小的两倍

HashSet底层其实维护着一个HashMap.

  • boolean add(E e)方法
    return map.put(e, PRESENT) == null

- HashTable和Properties

HashTable:

  • JDK1.0提供,线程安全,运行效率慢
  • 不允许null作为key或value

Properties:

  • HashTable的子类
  • 要求key和value都是String
  • 通常用于配置文件的读取

Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。
在IO流的学习中会详细学到Properties的使用

- TreeMap的使用

在类中实现Comparable接口

import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

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

        //1.添加元素
        Student1 s1 = new Student1("iFinder",167);
        Student1 s2 = new Student1("Nancy",123);
        Student1 s3 = new Student1("BobJoy",213);
        Student1 s4 = new Student1("JackyChan",254);

        //直接存储会报异常 java.lang.ClassCastException  Student1 cannot be cast to class java.lang.Comparable
        //需要提供比较的方法--实现comparable接口
        treeMap.put(s1,"云南");
        treeMap.put(s2,"北京");
        treeMap.put(s3,"美国");
        treeMap.put(s4,"英国");


        System.out.println("元素个数: " + treeMap.size());
        System.out.println(treeMap.toString());   //{name-Nancy stuID-123=北京, name-iFinder stuID-167=云南, name-BobJoy stuID-213=美国, name-JackyChan stuID-254=英国}
        //实现接口后,报错消失,元素按规定的规则进行排列
        //重写compareTo方法后,也可以实现将新建对象作为key传入去重的问题  但是value会替换为新的值
        treeMap.put(new Student1("Nancy",123),"天津");
        System.out.println(treeMap.toString());   //{name-Nancy stuID-123=天津, name-iFinder stuID-167=云南, name-BobJoy stuID-213=美国, name-JackyChan stuID-254=英国}

        //2.删除  .remove(K key)  .remove(K key,V value)  .clear()

        //3.遍历
        //3.1 keySet()遍历
        for(Student1 sut:treeMap.keySet()){
            System.out.println("Key- " + sut.toString() + " Value- " + treeMap.get(sut));
        }

        //3.2 entrySet()遍历
        for(Map.Entry<Student1,String> entry:treeMap.entrySet()){
            System.out.println("Key: " + entry.getKey() + " Value: " + entry.getValue());
        }
        //4.判断 .containsKey()  .containsValue()
    }
}
class Student1 implements Comparable<Student1>{
    private String name;
    private int stuID;
    //无参构造
    public Student1() { }
    //有参构造
    public Student1(String name, int stuID) {...}
    public String getName() {...}
    public void setName(String name) {...}
    public int getStuID() {...}
    public void setStuID(int stuID) {...}
    @Override
    public String toString() {...}
    @Override
    public int compareTo(Student1 o) {
        //按学号大小进行排序
        int n1 = this.stuID - o.getStuID();
        return n1;
    }
}

定制比较

import java.util.Comparator;
import java.util.TreeMap;

/**
 * 比较器定义比较方式
 */
public class TreeMapTest2 {
    public static void main(String[] args) {
        TreeMap<Student2,String> treeMap = new TreeMap<>(new Comparator<Student2>() {
            @Override
            public int compare(Student2 o1, Student2 o2) {
                int n1 = o1.getStuID() - o2.getStuID();

                return n1;
            }
        });

        //1.添加元素
        Student2 s1 = new Student2("iFinder",167);
        Student2 s2 = new Student2("Nancy",123);
        Student2 s3 = new Student2("BobJoy",213);
        Student2 s4 = new Student2("JackyChan",254);

        //直接存储会报异常 java.lang.ClassCastException  Student1 cannot be cast to class java.lang.Comparable
        //定制比较,将定制比较对象作为参数传入
        treeMap.put(s1,"云南");
        treeMap.put(s2,"北京");
        treeMap.put(s3,"美国");
        treeMap.put(s4,"英国");


        System.out.println("元素个数: " + treeMap.size());
        System.out.println(treeMap.toString());   //{name-Nancy stuID-123=北京, name-iFinder stuID-167=云南, name-BobJoy stuID-213=美国, name-JackyChan stuID-254=英国}
        //定制比较后,报错消失,元素按规定的规则进行排列
        //定义定制比较后,也可以实现将新建对象作为key传入去重的问题  但是value会替换为新的值
        treeMap.put(new Student2("Nancy",123),"天津");
        System.out.println(treeMap.toString());   //{name-Nancy stuID-123=天津, name-iFinder stuID-167=云南, name-BobJoy stuID-213=美国, name-JackyChan stuID-254=英国}


    }
}

class Student2{
    private String name;
    private int stuID;
    //无参构造
    public Student2() { }
    //有参构造
    public Student2(String name, int stuID) {...}
    public String getName() {...}
    public void setName(String name) {...}
    public int getStuID() {... }
    public void setStuID(int stuID) {...}
    @Override
    public String toString() {...}

}

TreeSet与TreeMap的关系

  • TreeSet底层维护一个TreeMap
    TreeSet(){
    this(new TreeMap<E, Object>()) }
    add(){
    return m.put(e, PRESENT) == null }

②Collections工具类

概念:Collections是集合的工具类,定义了除了存取以外的集合常用方法

方法说明
public static void reverse(List<?> list)反转集合中元素的顺序
public static void shuffle(List<?> list)随机重置集合元素的顺序
public static void sort(List<?> list)升序排序(元素必须实现Comparable接口)
static <T> int binarySearch​(List<? extends Comparable<? super T>> list, T key)使用二分查找搜索指定列表,获得指定对象
static <T> void copy(List<? super T> dest, List<? extends T> src)将一个元素从一个列表复制到另一个列表
package com;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CollectionsTool {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        //添加数据
        int[] in = {20,5,12,30,6,18};
        for (int i : in) {
            list.add(i);
        }

        //1.排序
        System.out.println(list.toString());   //[20, 5, 12, 30, 6, 18]
        Collections.sort(list);
        //Collections.sort(List<> list, Comparator<> ...);  可以定制排序比较的方法
        System.out.println(list.toString());   //[5, 6, 12, 18, 20, 30]

        //2.binarySearch() 二分查找
        int i = Collections.binarySearch(list,30);
        System.out.println(i);   //如果找到 i >= 0(元素位置)  没找到返回 -1

        //3.拷贝 copy()
        List<Integer> dest = new ArrayList<>();
        for (int i1 = 0; i1 < list.size(); i1++) {
            dest.add(0);
        }
        Collections.copy(dest,list);    //直接copy会报错,需要将二者的大小设置为相同
        System.out.println(dest);   //添加空数据后copy成功

        //4.反转 reverse()
        Collections.reverse(list);
        System.out.println(list);   // [30, 20, 18, 12, 6, 5]

        //5.打乱  shuffle();
        Collections.shuffle(list);
        System.out.println(list);   //[18, 12, 5, 30, 20, 6]
        Collections.shuffle(list);
        System.out.println(list);   //[5, 18, 6, 20, 30, 12]

        //6.将集合转为数组
        Integer[] arr= list.toArray(new Integer[10]);  //[]中的长度需要小于list长度,大于list长度,多出来的容量为空
        System.out.println(arr.length);
        System.out.println(Arrays.toString(arr));   //[18, 12, 30, 5, 20, 6, null, null, null, null]

        //7.将数组转为集合
        String[] names = {"iFinder","Nancy","BobJoy"};
        List<String> list1 = Arrays.asList(names);   //受限集合,不能添加和删除元素  因为数组长度固定,新建后不能改变长度
        //list1.remove(1);   java.lang.UnsupportedOperationException
        System.out.println(list1.toString());   //[iFinder, Nancy, BobJoy]
        
        //特例: 基本类型集合转为集合组要转为包装类
        //int[] nums = {100,200,300,400};
        Integer[] nums = {100,200,300,400};
        List<Integer> list2 = Arrays.asList(nums);
        

    }
}

③集合总结

  • 集合的概念:
    集合是对象的容器,和数组类似,定义了对多个对象进行操作的常用方法
  • List集合
    有序、有下标、元素可以重复(ArrayList–数组、LinkedList–双向链表、Vector)
  • Set集合
    无序、无下标、元素不可以重复(HashSet–哈希表、TreeSet–红黑树)
  • Map集合
    存储一对数据,无序、无下标,键值不可以重复,值可以重复
  • Collections工具
    集合的工具类,定义了除了存取以外的集合的常用方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值