Lesson18_Map_Set_Collections

36 篇文章 0 订阅
33 篇文章 0 订阅

0# Lesson18_Map_Set_Collections

回顾

Iterable ---- Iterator

Collection

List 有序、可重复

ArrayList 数组

LinkedList 链表

Set

  • Set继承与Collection方法上与List一样
  • 底层是Map,认为你的元素就是作为底层Map的键
  • 无序的,不能重复
HashSet
  • 底层就是HashMap,实际使用的就是HashMap的键
  • 键可以为null,只能有一个
  • 元素不重复,可以包含null值。
  • 不能排序
TreeSet
  • 底层就是TreeMap,实际使用的就是TreeMap的键
  • 不能有null值
  • 必须要有排序
  • 元素不重复,要求排序的,不能包含null值的。

Map

  • 键值对

  • 顶级接口

  • 键是唯一的。值可以重复

  • 键可以为null的。值也是可以为null。键只能有一个null。

  • entry将键值作为整体保存的

    @Test
    public void test05() {
        Map<Integer,String> map = new HashMap<>();
        //存入一个键值对
        map.put(1,"abc");
        map.put(2,"bcd");
        map.put(3,"ljl");
        map.put(4,"luiliu");
        map.put(5,"iuwiy");
        //如果存入的键已经存在,会将原来的值覆盖掉
        map.put(1,"ytg");
        //情况键值
        //map.clear();
        //判断是否包含某个键
        boolean b = map.containsKey(2);
        System.out.println(b);
        System.out.println("----------------");
        //判断是否包含某个值
        boolean abc = map.containsValue("abc");
        System.out.println(abc);
        System.out.println("----------------");
        //通过给定的键获取对应的值
        String s = map.get(1);
        System.out.println(s);
        System.out.println("----------------");
        //判断是否为空
        map.isEmpty();
        //通过键删除一对元素
        map.remove(1);
        //返回所有的值
        Collection<String> values = map.values();
        values.forEach(System.out::println);
        System.out.println("----------------");
        //返回entry类型的set集合
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        for (Map.Entry<Integer, String> entry : entries) {
            System.out.println(entry);
        }
        System.out.println("----------------");
        //返回所有的键,存入set集合
        Set<Integer> integers = map.keySet();
        Iterator<Integer> iterator = integers.iterator();
        while (iterator.hasNext()) {
            Integer next = iterator.next();
            System.out.println(next+"="+map.get(next));
        }
    }
    
HashMap
  • Map的一个子类
  • 数据结构是hash表结构的
  • hash表=数组+链表(红黑树=自平衡的二叉树=分支)
  • 数组你认为的那个数组
  • 二叉树,以链表为基础实现的。第一个数作为根,后面的数依次比较大小,如果大于跟,存到右边,如果小,左边,hashcode
  • 在这里插入图片描述
    • 二叉树的缺点就是如果跟定义不合适失去平衡,某一条分支太重
  • 为了解决二叉树是缺点,我们1.8以后不再二叉树(单边多余7个,总数超过18个),将二叉树转为红黑树
  • 红黑树的特点:
    • 相比二叉树有自平衡(重新定义根节点)
      • 左旋:往左边转
      • 右旋:往右边转
    • 所有的节点,要么是黑的,要么是红的
    • 根节点一定是黑的
    • 所有的尾节点一定是黑的
  • 先得到键的hash值,通过hash值得到数组中的下标,存入进去
  • 如果得到的两个键的hash的下标一样,再调用equals比较
  • 如果equals比较相等,认为键相等,值覆盖
  • 如果equals比较不想等。通过二叉树的形式连在后面
  • 1.8以前,依次往后连接,之后,往前连接,当链表长度超过8个,转为二叉树
  • 当同一个下标下的二叉树到了转换的条件(一边比另一半多6个或者整体到64个),就转为红黑树了
  • 源码分析
    • DEFAULT_INITIAL_CAPACITY = 1 << 4;初始容量16个
    • MAXIMUM_CAPACITY = 1 << 30;最大容量
    • DEFAULT_LOAD_FACTOR = 0.75f;加载因子,可以大于1的
    • 扩容的时候直接增加一倍,容量始终是2的幂方
    • TREEIFY_THRESHOLD = 8;链表转二叉树
    • UNTREEIFY_THRESHOLD = 6;二叉树失重
    • MIN_TREEIFY_CAPACITY = 64;重新转为链表的个数
@Test
    public void test02(){
        HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put("1","aa");
        hashMap.put("2","bb");
        hashMap.put("3","cc");
        hashMap.put("4","dd");
        hashMap.put("5","ee");
        //map.clear();
        //是否元素为空
        boolean empty = hashMap.isEmpty();
        System.out.println("是否元素为空 = " + empty);
        //长度
        int size = hashMap.size();
        System.out.println("长度 = " + size);
        //修改
        hashMap.replace("2","hh");
        //是否包含值
        String d = hashMap.get("d");
        System.out.println("d = " + d);
        //删除
        hashMap.remove("3");
        //键
        Set<String> strings = hashMap.keySet();
        System.out.println("键 = " + strings);
        //键值
        Set<Map.Entry<String, String>> entries = hashMap.entrySet();
        System.out.println("键值 = " + entries);
        //值
        Collection<String> values = hashMap.values();
        System.out.println("值 = " + values);
        //迭代
        Iterator<Map.Entry<String, String>> iterator = entries.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
  • hashMap线程不安全
  • 如果涉及到多线程的操作,要使用HashMap的话,可以使用它的代替品
  • ConcurrentHashMap:线程安全的,扩容时
  • HashTable:方法都是线程安全的
TreeMap
  • 键不能为空
  • 所有的元素必须是可以排序
  • 要么键的对象类型实现了自然排序,要么构造方法中传入比较器
  • 底层使用的是红黑树
  • 效率比HashMap低
  • 如果需要键有序排列的,使用
  • 一般使用外部的比较器
  • 外部传入的比较器的优先级高于自然比较的
@Test
    public void test06() {
        TreeMap<Users,String> map = new TreeMap<>((u1,u2) ->
            u1.getId()-u2.getId()
        );
        map.put(new Users(1,"张三","zhangsan"),"张三");
        map.put(new Users(4,"赵六","zhaoliu"),"赵六");
        map.put(new Users(2,"李四","lisi"),"李四");
        map.put(new Users(5,"孙七","sunqi"),"孙七");
        map.put(new Users(3,"王五","wangwu"),"王五");
        Set<Map.Entry<Users, String>> entries = map.entrySet();
        Iterator<Map.Entry<Users, String>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
  • 实现SortedMap

Collections

  • 类似于Arrays
  • 操作集合的工具类
  • 都是静态方法。直接用
 @Test
    public void test07() {
        HashSet<Users> set = new HashSet<>();
        //针对元素拥有自然排序的List集合进行排序
        Collections.sort(new LinkedList<String>());
        //对List集合,根据给定的比较器进行排序
        Collections.sort(new ArrayList<String>(),(s1,s2) -> s2.length()-s1.length());
        //返回一个空的List集合
        List emptyList = Collections.EMPTY_LIST;
        //返回一个空的Set集合
        Set emptySet = Collections.EMPTY_SET;
        //返回一个空的Map集合
        Map emptyMap = Collections.EMPTY_MAP;
        Collection<String> collection = new HashSet<>();
        //添加多个元素到参数集合中
        Collections.addAll(collection,"abc","bcd");
        ArrayList<Integer> list = new ArrayList<>();
        //二分查找,从参数集合中查找参数给定的元素,返回下标
        int i = Collections.binarySearch(list, 3);
        //将元素全部填充到集合中
        Collections.fill(list,2);
        //返回一个String类型的只有参数一个元素的List集合
        Collections.singletonList("abc");
        //返回一个String类型的只有参数一个元素的Set集合
        Collections.singleton("abc");
    }

Propertry

/**
 * @Author: 邪灵
 * @Date: 2020/11/24 14:34
 * @Description:
 * @version: 1.0
 */
public class Demo {
    @Test
    public void test01() throws IOException {
        Properties properties = new Properties();
        //存入一条记录,键值对,都是String类型
        properties.setProperty("key","values");
        //修改一条记录,如果没有对应的键,则无反应
        properties.replace("key1","values1");
        //存入一条记录,同setProperty方法
        properties.put("url","jdbc:mysql:///test");
        properties.put("name","root");
        properties.put("pass","root");
        //通过键获取值,与put方法相对
        properties.get("key");
        //通过键获取值,等同于get方法,与getProperty方法对应
        properties.getProperty("key");
        //判断是否包含某个键
        properties.containsKey("key");
        //判断是否包含某个值
        properties.containsValue("values");
        //判断是否包含某个值,同上
        properties.contains("values");
        //获取一个枚举器,包含都是值,没有键
        Enumeration<Object> elements = properties.elements();
        System.out.println("---------枚举器遍历值----------");
        while (elements.hasMoreElements()) {
            //通过枚举器遍历所有的值
            System.out.println(elements.nextElement());
        }
        //获取entry类型的set集合,用于遍历迭代
        Set<Map.Entry<Object, Object>> entries = properties.entrySet();
        System.out.println("---------entry遍历---------");
        for (Map.Entry<Object, Object> entry : entries) {
            System.out.println(entry);
        }
        //获取所有的值,同keyset方法
        properties.keys();
        //通过流的方式加载文件中的数据到集合中
        properties.load(new FileInputStream("file"));
        //获取所有的键,再通过键取到对应的值
        Set<Object> objects = properties.keySet();
        System.out.println("---------keyset遍历---------");
        for (Object object : objects) {
            System.out.println(object+"=="+properties.get(object));
        }
    }
}

【源码任务】
1.证明HashMap的容量是2的幂,即使是通过构造方法人为指定了容量,最后也会是2的幂。
2.证明Tree结构比较元素大小时,优先使用的Comparator的规则,而不是Comparable的规则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值