打卡双列集合

一、Map概述

  双列集合是每个元素都有键与值两部分组成的集合,记录的是键值对映射关系,将键值对存储到容器中,在查找的时候可以通过键找到值。

Map集合体系图
双列集合:Map<K,V>

如果实现了Map接口的集合类,具备特点:存储的数据都是以键值对的形式存在的,键不可重复,值可以重复
-----| HashMap
-----| TreeMap
-----| HashTable
在这里插入图片描述
Map集合特点:
1、Map集合是一个双列集合,一个元素包含两值(一个key,一个value)
2、Map集合中的元素,key和value的数据类型可以相同,也可以不同
3、Map集合中的元素,key是不允许重复的,value是可以重复的
4、Map集合中的元素,key和value是一一对应的

Map常用API

V put(K key, V value); //存储键值,如果键值存在,则使用新值替换旧值,返回旧值。如果键不存在,则直接存储,返回null
V remove(Object key);//根据键删除键值对,返回键对应的值。如果键不存在,则返回null
V get (Object key); //根据键找对应的值,如果键存在,则返回null。
Int size(); //获得键值对的个数
boolean containsKey(Object key); //判断集合中是否包含对应的键,包含返回true,否则返回false
boolean isEmpty(); //判断集合是否为空,有元素返回false,否则返回true

遍历Map集合的四种方式

1、keySet(); keySet方法是将Map中的所有键存到一个Set集合中,并返回Set集合。
缺点:返回键,还要去找值,遍历效率低。
2、values(); 将所有的value存放到一个collection集合中返回。
缺点:只能返回所有的值,没有键
3、entrySet();//entrySet 将所有的Key和Value存放到一个Entry实现中返回
4、过forEach();方法遍历(JDK1.8特性)

方法一:keySet();实现遍历
在这里插入图片描述
结果:

键:语文,值:112
键:英语,值:80
键:体育,值:100
键:数学,值:91
其中Map集合中的长度是4

方法二:values(); 遍历
在这里插入图片描述
结果:

值:112
值:80
值:100
值:91

方法三:entrySet(); 遍历
在这里插入图片描述
结果:

键:语文
值:112
键:英语
值:80
键:体育
值:100
键:数学
值:91

方法四:通过forEach方法进行迭代

 public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("语文",110);
        map.put("数学",93);
        map.put("英语",26);

        map.forEach((key, value) -> {
            System.out.println(key + ":" + value);
        });    
    }

Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。

1.1、HashMap

java.util.HashMap<K,V>集合 implements Map<K,V>接口

HashMap集合的特点:

1.HashMap集合底层是哈希值:查询的速度特别的快
JDK.8之前:数组+单向链表
JDK.8之后:数组+单向链表/红黑树(链表的长度超过8):提高查询的速度
2.HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
HashMap集合:可以存储null值,null键

HashMap的存储原理
  往HashMap添加元素的时候,首先会调用键的hashCode方法得到元素的哈希值,然后经过运算算出该元素在哈希表中的存储位置。
情况一:
  如果算出的位置目前没有任何元素存储,那么该元素可以直接添加到哈希表中。
情况二:
  如果算出的位置目前已经存在其他元素,那么还会调用该元素的equals方法与这个位置上的元素进行比较,如果equals方法返回的是false,那么该元素允许被存储,如果equals方法返回的是true,那么该元素被视为重复元素,不允许存储。

HashMap和Set集合区别

1、HashMap和Set底层都是基哈希表实现的,判断元素是否重复都需要重写equals和HashCode方法
2、HashMap是双列集合,Set是单列集合,都是存储无序的集合
3、HashMap如果存在重复元素,后面存的元素会覆盖前面的Set集合如果存在重复元素,那么元素将不被存入。

1.2、LinkedHashMap

  HashMap保证了元素唯一,并且查询速度很快,可是成对元素存入进去的时候是没有顺序的,那么要保证存储有序,还需要速度怎么办呢?
  在HashMap下有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构,记录元素的顺序,所以LinkedHashMap是一个有序的集合。
例如:
在这里插入图片描述

LinkedeHashMap存储顺序一致,不可重复。
HashMap是存储顺序不一致,也是不可重复。
更推荐使用LinkedeHashMap

1.3、HashTable

java.util.Hashtable<K,V>集合 implements Map<k,V>接口

HashTable特点:

Hashtable:底层也是一个哈希表,是一个线程安全的、同步的集合,是单线程集合,速度慢
Hashtable集合:不能存储null值,null键
Hashtable集合和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
Hashtable的子类properties依然活跃在历舞台
Properties集合是一个唯一和I/O流相结合的集合

面试题:

Hashtable 和 HashMap的区别:
(1) Hashtable 线程同步,安全,速度慢
(2) HashMap 线程不同步,不安全,速度快
(3) 前者不允许使用null键null值 , 后者允许使用null键null值

1.4、TreeMap

java.util.TreeMap<K,V>集合 implements Map<k,V>接口

TreeMap 主要事项:

1、往TreeMap添加元素的时候,如果元素的键具备自然顺序,那么就会按照键的自然顺序进行排列存储
2、如果键不具备自然顺序特性,那么键所属于的类必须要实现Comparable接口,把键的比较规则方法卸载comparaTo方法上
3、如果元素的键不具备自然排特性,而且键所属的类也没有实现Comparable接口,那么就必须在创建TreeMap对象的时候传如比较器

TreeMap使用案例:
Exam类实现比较器

class Exam implements Comparable<Exam>{
	
	int score; //成绩
	String subject;
	
	public Exam(int score, String subject) {
		super();
		this.score = score;
		this.subject = subject;
	}
	
	@Override
	public String toString() {
		
		return this.subject+":"+this.score;
	}

	@Override
	public int compareTo(Exam o) {
		
		return this.score - o.score;
	}
}

自定义比较器

class My_comparator implements Comparator<Exam>{


	@Override
	public int compare(Exam o1, Exam o2) {
		
		return o1.score - o2.score;
	}
}

main方法:

 public static void main(String[] args) {
        //1、具有排序特性的对象
        TreeMap<Character,Integer> tree = new TreeMap<Character,Integer>();
        tree.put('b', 10);
        tree.put('a', 66);
        tree.put('d', 28);
        tree.put('c', 102);

        System.out.println(tree); //具有排序特性的键会按键的排序特性排序输出

        //2、不具备排序特性的对象
        TreeMap<Exam,String> tree2 = new TreeMap<Exam,String>();
        tree2.put(new Exam(91,"数学"), "001");
        tree2.put(new Exam(86,"英语"), "002");
        tree2.put(new Exam(110,"语文"), "003");
        tree2.put(new Exam(60,"物理"), "004");

        System.out.println("tree2:"+tree2); //不具有排序特性的键需要重写


        //3、不具备排序特性的对象,且不实现comparable接口,必须传入比较器
        My_comparator comparator = new My_comparator();
        TreeMap<Exam,String> tree3 = new TreeMap<Exam,String>(comparator);
        tree3.put(new Exam(91,"数学"), "001");
        tree3.put(new Exam(86,"英语"), "002");
        tree3.put(new Exam(110,"语文"), "003");
        tree3.put(new Exam(60,"物理"), "004");

        System.out.println("tree3:"+tree3); //不具有排序特性的键需要重写
    }

结果:
{a=66, b=10, c=102, d=28}
tree2:{物理:60=004, 英语:86=002, 数学:91=001, 语文:110=003}
tree3:{物理:60=004, 英语:86=002, 数学:91=001, 语文:110=003}

HashTable 是线程安全的一个集合,不允许 null 值作为一个 key 值或者 Value 值;
HashTable 是 sychronize,多个线程访问时不需要自己为它的方法实现同步,而 HashMap 在被多个线程访问的时候需要自己为它的方法实现同步

总结:

(1)TreeMap是有序存储的,HashMap和HashTable是无序存储的。
(2)HashMap 是线程不安全的,HashMap 是一个接口,是 Map 的一个子接口,是将键映射到值得对象,不允许键值重复,允许空键和空值;由于非线程安全。HashMap 的效率要较 HashTable 的效率高一些.
(3)HashTable 是线程安全的一个集合,不允许 null 值作为一个 key 值或者 Value 值;
(4)HashTable 是 sychronize,多个线程访问时不需要自己为它的方法实现同步,而 HashMap 在被多个线
程访问的时候需要自己为它的方法实现同步。

二、JDK9对集合添加的优化

  在JDK9中,添加了集中集合工厂方法,更方便创建少量元素的集合和map实例。新的List、Set、Map的静态工厂方法可以更方便的创建集合的不可变实例。

JDK9新特性
List接口、Set接口、Map接口:里面增加了一个静态的方法of,可以给集合一次性添加多个元素
static <E> List<E> of (E...elements)
使用前提:
  当集合中存储的元素个数已经确定了,变数不在改变时候使用。

注意事项:
1、of方法只使用于List接口、Set接口、Map接口。不使用于接口的实现类
2、of方法返回值是一个不能改变的集合,单列集合不能再使用add,双列集合不能使用put方法添加元素,会抛出异常。
3、除List集合外,Set接口和Map接口在调用of方法的时候不能有重复的元素,否则会抛出异常。

例如:

public static void main(String[] args) {
    //List可存储重复元素
    List<String> list = List.of("a","b","c","d","a","c");
    System.out.println(list.toString());

    //list.add("w"); false,使用了of之后元素个数确定,不能再使用add方法增加元素
 }
public static void main(String[] args) {
        //Set不可存储重复元素
        Set<String> list = Set.of("a","b","c");
        System.out.println(list.toString());
    }
//Map不可存储重复元素
Map<String,Integer>  map = Map.of("语文",110,"数学",92,"英语",92);
System.out.println(map.toString());
//map.put("化学",88); false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值