Map双列集合

Map:存储双列数据,存储key-value键值对数据

  • HashMap:作为Map的主要实现类;线程不安全,效率高;可以存储null的key和value

    • LinkedHashMap:保证在遍历元素时可以按照添加的顺序遍历。

      原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。

      对于频繁遍历的操作,此类执行效率高于HashMap

  • TreeMap:保证按照添加的key-value进行排序,实现排序遍历,此时考虑key的自然排序和定制排序,底层使用红黑树

  • hashtable:作为古老的实现类;线程安全,效率底;不能存储null的key和value

    • Properties:常用来处理配置文件。key和value都是String类型

HashMap底层:数组+链表(jdk7及之前)

数组+链表+红黑树(jdk8)

HashSet底层使用的是HashMap,Set的值存储在Map的key位置,而value位置存储的是一个类对象的Object,无实际意义

HashMap结构理解

  • HashMap中的key:无序的、不可重复的 ————> key所在的类要重写equals()和hashCode()
  • HashMap中的value:无序的、可重复的 ————> value所在的类要重写equals()
  • 一个键值对:key-value构成了一个Entry对象,Map中的Entry是无序的,不可重复复的

注意

  • key所在的类要重写equals()和hashCode()
  • value所在的类要重写equals()
  • 当key比较一致的时候,新的value会替换旧的value

Map中定义的方法

增、删、改

  • V put(K key, V value):将指定的key-value添加到(或修改)当前map对象中
  • void putAll(Map m):将参数的m中所有的key-value添加到map中
  • V remove(Object key):删除指定key的key-value,并返回value
  • void clear():清空map中所有数据

元素查询的方法

  • V get(Object key):返回key对应的value,无则返回null;
  • boolean containsKey(Object key):是否包含指定key
  • boolean containsValue(Object value):是否包含指定的value
  • int size():返回Map中键值对的个数
  • boolean isEmpty():判断map是否为空
  • boolean equals(Object o):判断当前map与参数对象是否相等

元视图的操作方法

  • Set keySet() 获取map中包含所有key的Set对象集合
  • Collection values() 获取map中包含的value的Collection集合
  • Set<Map.Entry<K,V>> entrySet() 获取map中所有key-value构成Entry的Set集合

HashMap

增删改

@Test
public void test1() {
    HashMap<String,Integer> map = new HashMap<>();
    //put(K key, V value)
    map.put("小明",18);
    map.put("小红",16);
    map.put("小军",17);
    map.put("小明",16);   //第二次添加覆盖了原来的value值,相当于修改了数据
    System.out.println(map);

    HashMap<String,Integer> map1 = new HashMap<>();
    map1.put("小强",19);
    map1.put("小兰",15);

    //putAll(Map m)
    map.putAll(map1);
    System.out.println(map);

    //remove(Object key)
    map.remove("小明");
    System.out.println(map);

    //clear()
    map.clear();
    System.out.println(map);
}

元素的查询方法

@Test
public void test2() {
    HashMap<String,Integer> map = new HashMap<>();
    map.put("小明",18);
    map.put("小红",17);
    map.put("小兰",17);

    //V get(Object key)
    Integer value = map.get("小明");
    System.out.println(value);

    //containsKey(Object key):是否包含指定key
    boolean flag;
    flag = map.containsKey("小红");
    System.out.println(flag);
    flag = map.containsKey("小娜");
    System.out.println(flag);

    //containsValue(Object value):是否包含指定的value
    flag = map.containsValue(17);
    System.out.println(flag);
    flag = map.containsValue(19);
    System.out.println(flag);

    //size()
    int size = map.size();
    System.out.println(size);

    //isEmpty():判断map是否为空
    flag = map.isEmpty();
    System.out.println(flag);

    //equals(Object o):判断当前map与参数对象是否相等
    HashMap<String,Integer> map1 = new HashMap<>();
    map1.put("小明",18);
    map1.put("小兰",17);
    map1.put("小红",17);
    flag = map.equals(map1);
    System.out.println(flag);
}

元视图的操作方法,遍历map元素

@Test
public void test3() {
    HashMap<String,Integer> map = new HashMap<>();
    map.put("小明",18);
    map.put("小红",17);
    map.put("小兰",17);

    //遍历所有的key
    //Set<K> keySet() 获取map中包含所有key的Set对象集合
    Set<String> keySet = map.keySet();
    Iterator<String> keyIterator = keySet.iterator();
    while (keyIterator.hasNext()) {
        System.out.println(keyIterator.next());
    }

    //遍历所有的value
    //Collection<V> values() 获取map中包含的value的Collection集合
    Collection<Integer> values = map.values();
    for (Integer value : values) {
        System.out.println(value);
    }

    //遍历所有的key-value
    //方式一:通过Set<Map.Entry<K,V>> entrySet() 获取map中所有key-value构成Entry的Set集合
    Set<Map.Entry<String, Integer>> entries = map.entrySet();
    Iterator<Map.Entry<String, Integer>> entryIterator = entries.iterator();
    while (entryIterator.hasNext()) {
        System.out.println(entryIterator.next());
    }

    //方式二:通过key,在map中查找value
    Set<String> keySet1 = map.keySet();
    Iterator<String> keyIterator1 = keySet1.iterator();
    while (keyIterator1.hasNext()) {
        String nextKey = keyIterator1.next();
        System.out.println(nextKey + " --> " + map.get(nextKey));
    }
}

HashMap实现原理

jdk7为例

(1)HashMap map = new HashMap();

  • 实例化后,底层创建了长度为16的一维数组Entry[] table

(2)map.put(key1,value1);

  • 首先调用key1所在类的hashCode()计算出key1的哈希值,此哈希值经过某种算法计算之后,得到在Entry[]数组中的存放位置。

  • 如果此位置上没用数据,此时key1-value1 添加成功。————情况1

  • 如果此位置上有一个或多个数据(以链表的形式进行存储),比较key1和已经存在的数据的哈希值:

    • 如果key1的哈希值与已经存在的元素的key的哈希值不同,此时key1-value1添加成功 ————情况2
    • 如果key1的哈希值与预警存在的某个元素的key哈希值相同,继续比较:调用key所在类的equals(),比较key值
      • 如果equals()返回false:此时key1-value1添加成功。
      • 如果equals()返回true:使用value1替换旧的value

补充

  • 一个位置上存在多个元素,元素使用链表的方式进行存储

  • 在不断的添加过程中,会涉及到扩容问题,默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来

jdk8 相交于jdk7在底层实现方面的不同

  1. new HashMap():底层没有立即创建一个长度为16的数组

  2. jdk8底层的数组是:Node[],而非Entry[]

  3. 首次调用put()时,底层创建长度为16的Node[]数组

  4. jdk7底层结构只有:数组+链表。jdk8底层结构:数组+链表+红黑树。

    当数组的某个索引位置上的元素以链表的形式存储的数据 > 8且当前数组长度 > 64时,此索引位置上的所有数据改为红黑树存储

TreeMap

注意

TreeMap 按照key进行排序的,通过Java的比较器进行比较排序,所以key的类需要实现Comparable接口,并且存储的元素key都是同一个类的对象

排序

  • 自然排序:key实现Comparable接口,重写compareTo()方法
  • 定制排序:在实例化key的时候构造器传入自定义的比较器Comparator对象

自然排序

添加的元素的key所在的类需要实现Comparable接口,重写compareTo()方法

@Test
public void test1() {
    //Person类中已经按照姓名从小到大,年龄从小到大的排序
    TreeMap<Person,String> map = new TreeMap<>();

    map.put(new Person("小明",18),"香蕉");
    map.put(new Person("小红",16),"苹果");
    map.put(new Person("小强",16),"猕猴桃");
    map.put(new Person("小钢",17),"菠萝");
    System.out.println(map);
}

定制排序

在创建Map对象的时候需要在构造器中传入自定义的比较器Comparator对象

//定制排序
@Test
public void test2() {
    //先按照年龄从小到大排序,然后按照姓名从小到大排序
    TreeMap<Person,String> map = new TreeMap<>(new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            int flag = o1.getAge() - o2.getAge();
            if(flag != 0) {
                return flag;
            } else {
                return o1.getName().compareTo(o2.getName());
            }
        }
    });

    map.put(new Person("小明",18),"香蕉");
    map.put(new Person("小红",16),"苹果");
    map.put(new Person("小强",16),"猕猴桃");
    map.put(new Person("小钢",17),"菠萝");
    System.out.println(map);
}

Properties

Properties:常用来处理配置文件。key和value都是String类型

使用Properties加载配置文件

@Test
public void test1() {
    Properties properties = new Properties();

    try(InputStream is = new FileInputStream("src/Map/jdbc.properties")) {

        properties.load(is);
        String name = properties.getProperty("name");
        String age = properties.getProperty("age");
        System.out.println(name + "-->" + age);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

jdbc.properties文件

name=mango
age=19
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值