Java Map

零、复习昨日

HashSet不允许重复元素,无序
HashSet去重原理:
先比较hashcode,如果hashcode不一致,直接存储
如果hashcode值一样,再比较equals
如果equals值为true,则认为完全一样,不存储即去重
否则存储

如果使用的是空参构造创建出的TreeSet集合,那么它底层使用的就是 自然排序,即放入TreeSet的元素都必须实现Comparable接口,重写方法comparTo

一、作业

  public static void main(String[] args) {
        String[] arr = {"a","b","c","a","b","c"};
        String[] strArr = setArray(arr);
        System.out.println(Arrays.toString(strArr ) );
    }

    // 第一题
    // 设计方法,将传入的数组去重后返回
    // 例如: 字符串数组:[“aa”,”bb”,”cc”,”aa”,”cc”,”bb”],将其去重变为[“aa”,”bb”,”cc”]
    public static String[] setArray(String[] arr) {

        // 遍历数组,取出一个,向set集合放一个,最后再变回数组
        HashSet<String> set = new HashSet<>( );
        for (String s : arr) {
            set.add(s);
        }
        String[] strArr = new String[set.size()];

        // 集合转数组
        String[] result = set.toArray(strArr);

        return result;
    }
注意: T[] toArray(T[] arr)
4 创建一个Teacher类 属性age name salary 
  创建10个Teacher对象 装入TreeSet中
  通过设置Teacher类 保证age大的在Treeset前面  
   age相同 
	salary小的在Treeset前面
    salary相同 name长度小的在Treeset前面
package com.qf.homework;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Teacher implements Comparable<Teacher>{

    private int age;
    private String name;
    private double salary;
    
    // 省略部分代码...

    @Override
    public int compareTo(Teacher o) {
        // 如果年龄相同,则继续判断
        if(o.getAge() - this.age == 0){
            // 再判断工资,如果工资相同,则继续判断
            if (this.salary - o.getSalary() == 0) {
                // 判断名字长度,如果名字长度一致,要保留该人名,所以不能返回0,随意返回一个1或者-1
                // 如果名字长度不一致,名字短的在前
                return this.name.length() - o.getName().length() == 0 ? 1 : this.name.length() - o.getName().length();
            } else {
                // 如果工资不同,工资低的在前
                return this.salary - o.getSalary() > 0 ? 1 : -1;
            }
        } else {
            // 如果年龄不同,年龄大在前
            return o.getAge() - this.age;
        }
    }
}
    public static void main(String[] args) {

        TreeSet<Teacher> treeSet = new TreeSet<>( );
        treeSet.add(new Teacher(18,"老邢",50000));
        treeSet.add(new Teacher(21,"老邢",50000));
        treeSet.add(new Teacher(19,"小老邢",40000));
        treeSet.add(new Teacher(19,"老邢",40000));
        for (Teacher teacher : treeSet) {
            System.out.println(teacher );
        }
    }

二、比较器排序

TreeSet是会对元素进行排序去重,有两种实现方案
第一种:使用空参构造方法创建出的TreeSet,底层使用自然排序,级元素要实现Compareable接口才能实现排序
第二种:可以使用有参构造,在创建TreeSet集合时,传入一个Compartor比较器,这样存入的元素就会按照该比较器指定的排序方案排序(不再使用默认的自然排序)
TreeSet(Comparator comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。使用步骤
1、自定义类实现Compartor接口,
2、重写Compar(T o1,T 02)方法
o1就是之前ComparTo方法中的this,即正在存储的元素
o2就是之前ComparTo方法中的o,即以前存储过的元素
方法返回值与之前comparTo方法的返回值一样
1)返回0 去重
2)返回负数放左边
3)返回正数放右边

练习: 把昨天的排序练习使用比较器排序再写一遍

学生语数外总成绩排序题目改写

public class StudentScore{

    private String name;
    private int chinese;
    private int math;
    private int english;
    // set get...
    // 有参 无参构造
}

三、Collections

类似于与Arrays,Collections是集合的工具类,方法都是静态的
Collections.reverse(List<?> list) 反转
Collections.shuffle(List<?> list) 混洗
Collections.sort(list<?> list) 排序,升序
ArrayList<Integer> list = new ArrayList<Integer>();
      list.add(3);
      list.add(2);
      list.add(5);
      list.add(4);
      list.add(1);

      System.out.println(list);
      // 反转
//      Collections.reverse(list);
//      System.out.println(list);

      // 混洗
//      Collections.shuffle(list);
//      System.out.println(list);
      
      // 排序,升序
      Collections.sort(list);
      System.out.println(list);

四、Map<k,v>

Map代表双列集合,一次存储一对键值对(k,v)
Map是个接口,代表是键映射到之的对象,一个Map不能包含重复的键,值允许重复。每个键最多只能映射到一个值,即可以通过键找到值,但不能通过值找到键.
方法都是非常常见的方法,但是Map是接口无法演示
Map有两个常用实现类
HashMap
TreeMap

五、HashMap

HashMap是Map的实现类,现在JDK 8 及以后底层是有数组+链表+红黑树实现
并允许使用 ==null== 值和 ==null== 键
HashMap存储的元素是 不保证迭代顺序、且存储的键不允许重复,值允许重复

除了非同步和允许使用 null 外,==HashMap== 类与 ==Hashtable== 大致相同

补充:==Hashtable== 是线程安全的map集合,效率低 ; HashMap是线程不安全的,效率高
ConcurrentHashMap即安全又高效的Map集合
HashMap的容量和扩容:初始值16,加载因子0.75,达到阈值12扩容到原来2倍
昨天学习的HashSet所有特性,其实就是HashMap的特性,包括去重原理

5.1 方法演示

构造方法

HashMap()
构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity)
构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity, float loadFactor)
构造一个带指定初始容量和加载因子的空 HashMap。
HashMap(Map<? extends K,? extends V> m)
构造一个映射关系与指定 Map 相同的新 HashMap。
方法

每个都很重要!!!!
    public static void main(String[] args) {

        // 创建空的HashMap;
        HashMap<String,Integer> map = new HashMap<>();
        System.out.println(map );

        // 添加元素,一次添加一对,键值
        // put方法的返回值,如果该键之前没有映射值,返回null
        // 如果该键之前映射的有值,则将值覆盖,返回上次的旧值
        Integer v1 = map.put("a",1);
        System.out.println(v1 );

        Integer v2 = map.put("a", 2);
        System.out.println(v2 );

        Integer v3 = map.put("d", 4);
        System.out.println(v3 );
        map.put("b",2);
        System.out.println(map );

        // 取出元素
        // 通过键返回值
        Integer v = map.get("a");
        System.out.println(v );

        // 集合大小(元素个数)
        System.out.println(map.size() );

        // 集合是否为空
        System.out.println(map.isEmpty() );

        // 清空集合
        //map.clear();

        // 集合大小(元素个数)
        //System.out.println(map.size() );

        // 集合是否为空
        //System.out.println(map.isEmpty() );

        // 移除元素,根据键移除整个键值对,返回值
        Integer a = map.remove("a");
        System.out.println(a );

        System.out.println(map );
        
        
        /**
         *  boolean containsKey(Object key)
         *           判断集合中是否包含指定键,有则返回 true。
         *  boolean containsValue(Object value)
         *           判断集合中是否包含指定值,有则返回 true。
         */
        System.out.println(map.containsKey("A"));
        System.out.println(map.containsValue(11));
    }

5.2 迭代/遍历

5.2.1 键值集

HashMap<String, Integer> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);
        
        // 键集遍历
        Set<String> keySet = map.keySet();
        // 获得迭代器
        Iterator<String> iterator = keySet.iterator();
        // while循环
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }

        System.out.println("\n-----------------");
        // foreach
        for (String key : keySet) {
            System.out.print(key + " ");

5.2.2 值集

HashMap<String, Integer> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);

        Collection<Integer> values = map.values();
        Iterator<Integer> iterator = values.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println("\n------------");
        for (Integer v : values) {
            System.out.print(v + " ");
        }

5.2.3 键值映射集[非常重要]

Entry是Map接口中的内部接口,代表是一个键值对,即包含键和值。
且该Entry接口中提供了关于操作单个键,值的方法
K getKey()
V getValue()
HashMap<String, Integer> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);

        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()) {
//            Map.Entry<String, Integer> entry = iterator.next();
//            String key = entry.getKey();
//            Integer value = entry.getValue();
//            System.out.println(key + "-->" + value);
            System.out.print(iterator.next() + " ");
        }

        System.out.println("\n----------------");

        for (Map.Entry<String, Integer> entry : entries) {
//            System.out.print(entry + " ");
            System.out.print(entry.getKey() + "-->" + entry.getValue() + " ");
        }

5.3 去重原理

HashMap的去重其实就是昨天讲的HashSet的去重,因为HashSet底层就是HashMap
在创建HashSet时,其实在底层创建了HashMap

在向set中添加元素时,其实是向map的key上添加
所以HashMap的键的去重原理就是
向键存储数据时,先调用键的hashcode()方法
如果hashcode值不一样则直接存储
如果hashcode值一样,再调用元素的equals()方法
如果equals方法返回false,则存储
如果equals方法返回true,则不存储

5.4 HashMap的应用

场景一: 适合有关联映射的场景

设计方法,传入字符串,输出该字符串中每个字符出现的次数,使用HashMap实现

例如: “abcHelloabcWorld”,输出 a出现2次,b出现2次,,,l出现3次,H出现1次

   /**
     * 倒推: a --> 3  b --> 2
     * @param str
     */
    public static void cishu(String str) {
        String[] strArr = str.split("");
        System.out.println(Arrays.toString( strArr) );

        HashMap<String, Integer> map = new HashMap<>( );

        for (int i = 0; i < strArr.length; i++) {
            String s = strArr[i];
            if (!map.containsKey(s)) {
                map.put(s,1);
            } else {
                Integer count = map.get(s);
                count++;
                map.put(s,count);
            }
        }

        // System.out.println(map );
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet( );
        for (Map.Entry<String,Integer> entry :entrySet) {
            String s = entry.getKey( );
            Integer count = entry.getValue( );
            System.out.println("字符"+s+",出现"+count+"次" );

        }
    }
场景二: Map可以当实体类对象
public class Student{
    private int age;
    private String name;
    // ...
    
}
Student s1 = new Student(18,"zs");
s1.getAge();
s1.getName();

使用Map模拟对象

HashMap<String, Object> stu = new HashMap<>( );
stu.put("age",18);
stu.put("name","zs");
stu.put("sex","男");
LinkedHashMap: ....

六、TreeMap

TreeMap底层是红黑树(平衡二叉树的一种)
同样式存储键值对,键不允许重复且还会排序
默认是根据键元素的自然顺序排序或者,根据创建TreeMap时指定的Comparator比较器来排序

6.1 方法演示

方法详见api
   public static void main(String[] args) {

        TreeMap<String, Integer> map = new TreeMap<>( );
        map.put("b",2);
        map.put("e",5);
        map.put("a",1);
        map.put("a",2);
        map.put("d",4);
        map.put("c",3);

        // 其他正常的map方法...
        // 三个遍历方法...

        // 特殊的,有关于头尾操作的方法
        // 获得排序后的第一个
        String key = map.firstKey( );

        // 获得排序后的第一个Entry
        Map.Entry<String, Integer> entry = map.firstEntry( );
        System.out.println(entry );
    }

6.2 TreeMap排序去重原理

昨天学习的TreeSet的底层其实就是TreeMap
创建TreeSet时,创建TreeMap
向set集合添加元素时,其实是向TreeMap的键添加元素
即TreeMap的排序去重原理是什么?其实如果自然排序就是compareTo(),如果是比较器排序就是compar()方法
方法返回0 去重
方法返回负数 放在树左侧

七、总结

集合体系中最重要最常见的两个集合是ArrayList,HashMap
其他的,
记住常用的API(crud和遍历)
记住List和Set区别
记住ArrayList和LinkedList区别
记住HashMap扩容,去重原理
记住TreeMap的排序去重原理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值