chapter11集合(2)

Map接口

键值对<key,value>

Interface Map<K,V>

    • 参数类型

      K - 由此地图维护的键的类型

      V - 映射值的类型

public class TestMap {
    public static void main(String[] args) {
        /*
        * 增加:put(K key, V value)
        * 删除:clear();remove(Object key);
        * 修改:
        * 查看:entrySet();get(Object key);keySet();values();size()
        * 判断:containsKey(Object key);containsValue(Object value);equals(Object o);isEmpty()
        * */
        //创建一个Map集合:唯一,无序
        Map<String,Integer> map=new HashMap<>();
        System.out.println(map.put("sky", 502));//null;put的返回值是v,即这里的integer
        map.put("lsj",426);
        map.put("yhm",456);
        map.put("zrp",1715110092);
        System.out.println(map.put("sky", 374));//502
        System.out.println(map.size());//4
        System.out.println(map);//{sky=374, lsj=426, zrp=1715110092, yhm=456}

        /*map.clear();清空
        System.out.println(map.size());//0
        System.out.println(map);//{}*/

        /*map.remove("sky");移除
        System.out.println(map.size());//3
        System.out.println(map);//{lsj=426, zrp=1715110092, yhm=456}*/

        System.out.println(map.containsKey("swy"));//false
        System.out.println(map.containsValue(426));//true

        Map<String,Integer> map2=new HashMap<>();
        map2.put("sky", 502);//null;put的返回值是v,即这里的integer
        map2.put("lsj",426);
        map2.put("yhm",456);
        map2.put("zrp",1715110092);
        map2.put("sky", 374);
        System.out.println(map==map2);//false
        System.out.println(map.equals(map2));//equals进行了重写比较的是集合中值,内容是否一样;true
        System.out.println(map.isEmpty());//判断是否为空;false

        System.out.println(map.get("sky"));//374

        //遍历:
        Set<String> set = map.keySet();//keySet()对集合中的key进行遍历查看
        System.out.println("===============");
        for(String s:set){
            System.out.println(s);
        }
        System.out.println(map.keySet());//[sky, lsj, zrp, yhm]

        //获取value的两种方式
        Collection<Integer> values = map.values();//values()对集合中的value进行查看
        System.out.println("===============");
        for(Integer i:values){
            System.out.println(i);
        }
        System.out.println(map.values());//[374, 426, 1715110092, 456]

        //不用values()方法对value进行遍历

        Set<String> set2 = map.keySet();
        for(String s:set2){
            System.out.println(map.get(s));
        }
        System.out.println("===============");
        Set<Map.Entry<String, Integer>> entries = map.entrySet();//返回set集合
        //Entry是Map接口里的一个内部接口
        for(Map.Entry<String, Integer> e:entries){
            System.out.println(e.getKey()+"-----"+e.getValue());
        }
    }
}

上面HashMap换成Hashtable,输出结果不变

HashMap实现类

特点:唯一,无序;不允许k的值重复

HashMap与Hashtable区别:

Map<String,Integer> map3=new Hashtable<>();
//map3.put(null,1010);//Exception in thread "main" java.lang.NullPointerException
//对于hashtable来说,key不可以是null值,存了会报错
Map<String,Integer> map4=new HashMap<>();
System.out.println(map4.put(null, 1010));//null
System.out.println(map4.put(null, 2020));//可以存放多个空
System.out.println(map4);//{null=2020}

LinkedHashMap实现类

特点:有序,唯一

LinkedHashMap<String,Integer> lmap=new LinkedHashMap<>();
lmap.put("asky",502);
lmap.put("bsky",502);
lmap.put("csky",502);
lmap.put("sky",502);
System.out.println(lmap);//{asky=502, bsky=502, csky=502, sky=502}

在这里插入图片描述

TreeMap实现类

1、key的类型为String类型

public class TestTreeMap {
    public static void main(String[] args) {
        Map<String,Integer> map=new TreeMap<>();
        map.put("bsky", 502);
        map.put("alsj",426);
        map.put("byhm",456);
        map.put("czrp",1715110092);
        map.put("dsky", 374);
        System.out.println(map.size());//5
        System.out.println(map);//{alsj=426, bsky=502, byhm=456, czrp=1715110092, dsky=374}
        //String底层已经实现了比较器
    }
}

2、key的类型是一个自定义的类型

(1)内部比较器

(2)外部比较器

Map<Student,Integer> m1=new TreeMap<>();
m1.put(new Student(19,168.3,"flili"),103);
m1.put(new Student(18,168.3,"blili"),123);
m1.put(new Student(11,168.3,"clili"),1023);
m1.put(new Student(17,168.3,"dlili"),111);
m1.put(new Student(16,168.3,"alili"),167);
m1.put(new Student(20,168.3,"glili"),88);
System.out.println(m1);//按自己定义的比较器进行排序
System.out.println(m1.size());//6

 Map<Student,Integer> m1=new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge()-o2.getAge();
            }
        });//匿名内部类的外部比较器

HashMap的简单原理

JDK1.7版本

提出问题:

public class OriHashMap {
    public static void main(String[] args) {
        //创建hashmap对象:存储的是双列数据,键值对key-value
        HashMap<Integer,String> hm=new HashMap<>();
        System.out.println(hm.put(12, "sky"));//null
        System.out.println(hm.put(7, "feifei"));//null
        System.out.println(hm.put(19, "lulu"));//null
        System.out.println(hm.put(12, "mingming"));//sky
        //这个12是sky的12还是mingming的12?
        System.out.println(hm.put(2, "yhm"));//null
        System.out.println(hm.size());//4
        System.out.println(hm);//{2=yhm, 19=lulu, 7=feifei, 12=mingming}
    }
}

答:12是sky的12

七上八下:jdk7链表头插法;jdk8尾插法
在这里插入图片描述
在这里插入图片描述

jdk1.7版源码
//1.hashmap的k,v值,在创建对象时确定
//hashmap的父类AbstractMap已经实现了Map接口,但源码中又单独实现了Map,这是多余的,错的,arraylist同理
public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable 
    //重要属性
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16,一会儿赋值给数组的长度
	static final int MAXIMUM_CAPACITY = 1 << 30;//定义了一个很大很大的数
	static final float DEFAULT_LOAD_FACTOR = 0.75f;//定义了一个值:0.75 装填因子,负载因子,加载因子
	transient Entry<K,V>[] table;//底层主数组
	transient int size;//集合中添加元素的数量
	int threshold;//定义了变量,没赋值默认为0-----》数组扩容的边界值
	final float loadFactor;//用来接收装填因子,负载因子,加载因子

在这里插入图片描述
在这里插入图片描述

put原理

put方法源码:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数组扩容原理

数组扩容的边界值是指?size超过12就扩容?

不是,是要size超过12且目标位置不为空才会扩容
在这里插入图片描述
在这里插入图片描述

经典面试题

1、装填因子,负载因子,加载因子为什么是0.75?

装填因子设置为1:空间利用率得到了很大的满足,很容易碰撞,产生链表------》查询效率低

装填因子设置为0.5:碰撞的概率第,扩容,产生链表的几率低------》查询效率高;空间利用率太低了

所以在0.5-1中取了一个中间值0.75
在这里插入图片描述

2、主数组的长度为什么必须为2^n?
在这里插入图片描述

HashSet底层原理

public class HashSet<E>{
    //重要属性:
    private transient HashMap<E,Object> map;
    private static final Object PRESENT = new Object();
    //构造器
    public HashSet() {
        map = new HashMap<>();
    }
    
	public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
}

TreeMap底层源码

在这里插入图片描述

二叉树就是红黑树
在这里插入图片描述

public class TreeMap<K,V>{
    //重要属性:
    //外部比较器
    private final Comparator<? super K> comparator;
    //树的根节点
    private transient Entry<K,V> root;
    //集合中元素的数量
    private transient int size = 0;
    //空构造器
    public TreeMap() {
        comparator = null;//如果使用空构造器,那么底层就不使用外部比较器
    }
    //有参构造器
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;//如果使用了有参构造器,那么相当于指定了外部比较器
    }
    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;
        Entry<K,V> right;
        Entry<K,V> parent;
        boolean color = BLACK;
	}
    public V put(K key, V value) {//K,V的类型在创建对象时确定
         //如果放入的时第一对元素,那么t的值为null
            Entry<K,V> t = root;//放入第二个元素时,root不为空,不走if
         	//如果放入的时第一个元素的话,走入这个if中
            if (t == null) {
                //自己与自己比较
                compare(key, key); // type (and possibly null) check
                //根节点确定为root
                root = new Entry<>(key, value, null);
                //size变成1
                size = 1;
                modCount++;
                return null;
            }
            int cmp;
            Entry<K,V> parent;
            // split comparator and comparable paths
         //将外部比较器赋值给cpr:
            Comparator<? super K> cpr = comparator;
         //cpr不等于null意味着创建对象时调用了有参构造器,指定了外部比较器
            if (cpr != null) {
                do {
                    parent = t;
                    cmp = cpr.compare(key, t.key);//将元素的key值做比较
                    //cmp返回int类型数据
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else//cmp==0;
                        //如果key的值一样,那么新的value替换老的value,但是key不变,key唯一
                        return t.setValue(value);
                } while (t != null);
            }//cpr等于null意味着创建对象时调用了空构造器,没有指定外部比较器,使用内部比较器
            else {
                if (key == null)
                    throw new NullPointerException();
                @SuppressWarnings("unchecked")
                    Comparable<? super K> k = (Comparable<? super K>) key;
                do {
                    parent = t;
                    cmp = k.compareTo(t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;//size加一操作
        modCount++;
        return null;
    }
}

TreeSet源码

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable{
    //重要属性:
    private transient NavigableMap<E,Object> m;
    private static final Object PRESENT = new Object();
    //调用空构造器时底层创建了一个TreeMap
    public TreeSet() {
    this(new TreeMap<E,Object>());
	}
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }
    //实际上时treemap的put方法
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
}

Collections工具类

public class TestCols {
    public static void main(String[] args) {
        //collections不支持创建对象,因为构造器私有化
        //属性和方法通过类名调用
        //常用方法:addAll
        ArrayList<String> list=new ArrayList<>();
        list.add("cc");
        list.add("aa");
        list.add("bb");

        Collections.addAll(list,"dd","ff");
        Collections.addAll(list,new String[]{"sky","lsj","yhm"});
        System.out.println(list);

        //sort升序排列
        Collections.sort(list);
        System.out.println(list);
        //binarySearch:前提,集合内容有序
        int i=Collections.binarySearch(list,"cc");
        System.out.println(i);

        //copy:把list2里面的内容替换到list里面
        ArrayList<String> list2=new ArrayList<>();
        Collections.addAll(list2,"tt","ss");
        Collections.copy(list,list2);
        System.out.println("============");
        System.out.println(list);
        System.out.println(list2);

        //fill:填充,把list2里面的所有内容填充为yy
        Collections.fill(list2,"yy");
        System.out.println(list2);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值