总结Java中的双列集合

目录

双列集合

双列集合的特点

集合体系结构

Map的常见API

Map的遍历方式

键找值

键值对

Lambda表达式

底层源码:

HashMap

HashMap的特点

案例

LinkedHashMap

TreeMap

TreeMap基本应用

需求1:

需求2:

案例

可变参数

Collections

Collections常用的API

案例

自动点名器1

自动点名器2


双列集合

双列集合的特点

① 双列集合一次需要存一对数据,分别为键和值

② 键不能重复,值可以重复

③ 键和值是一一对应的,每一个键只能找到自己对应的值

④ 键+值这个整体,我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”

集合体系结构

Map的常见API

Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的

方法名称说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数

put方法的细节:

含义:添加/覆盖

  1. 在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回nu11

  2. 在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。

package mymap;
​
import java.util.HashMap;
import java.util.Map;
/**
 * |        V put(K key,V value)         |               添加元素               |
 * | :---------------------------------: | :----------------------------------: |
 * |        V remove(Object key)         |         根据键删除键值对元素         |
 * |            void clear()             |         移除所有的键值对元素         |
 * |   boolean containsKey(Object key)   |       判断集合是否包含指定的键       |
 * | boolean containsValue(Object value) |       判断集合是否包含指定的值       |
 * |          boolean isEmpty()          |           判断集合是否为空           |
 * |             int size()              | 集合的长度,也就是集合中键值对的个数 |
 */
public class MapDemo1 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();
​
        //添加元素
        map.put("AAA","aaa");
        map.put("BBB","bbb");
        map.put("CCC","ccc");
​
        //打印集合
        System.out.println(map); //{AAA=aaa, CCC=ccc, BBB=bbb}
​
        System.out.println("----------------------------------------");
​
        //根据键删除键值对元素
        String result = map.remove("AAA");
        //打印被删除的值
        System.out.println(result); //aaa
​
        //打印集合
        System.out.println(map); //{AAA=aaa, CCC=ccc, BBB=bbb}
​
        System.out.println("----------------------------------------");
​
        //判断集合是否包含指定的键
        boolean keyResult = map.containsKey("BBB"); //true
        System.out.println(keyResult);
​
        System.out.println("----------------------------------------");
​
        //判断集合是否包含指定的值
        boolean valueResult = map.containsValue("bbb");
        System.out.println(valueResult); //true
​
        System.out.println("----------------------------------------");
​
​
        //移除所有的键值对元素
        map.clear();
​
        //打印集合
        System.out.println(map); //{}
​
        //判断集合是否为空
        boolean empty = map.isEmpty();
        System.out.println(empty); //true
​
        //集合的长度,也就是集合中键值对的个数
        int size = map.size();
        System.out.println(size); //0
​
​
    }
}

Map的遍历方式

键找值

获取所有的键,并把这些键放到一个单列集合中,遍历单列集合,得到每一个键,利用map集合中的键获取对应的值

public class MapDemo2 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();
​
        //添加元素
        map.put("AAA", "aaa");
        map.put("BBB", "bbb");
        map.put("CCC", "ccc");
​
        //遍历集合,键找值
        Set<String> keyResult = map.keySet();
        for (String key : keyResult) {
            String value = map.get(key);
            System.out.println(key + " = " + value);
        }
    }
}

键值对

通过entrySet方法获取所有的键值对对象,返回一个Set集合;

遍历这个Set集合,得到里面每一个键值对对象;

利用getKey() 和 getValue()方法获取键和值

public class MapDemo2 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();
​
        //添加元素
        map.put("AAA", "aaa");
        map.put("BBB", "bbb");
        map.put("CCC", "ccc");
​
        //遍历集合,键值对
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }
​
    }
}

Lambda表达式

方法名称说明
default void forEach(BiConsumer<? super K,? super V> action)结合lambda遍历Map集合

利用lambda表达式进行遍历

底层:其实就是利用第二种方式进行遍历,依次得到每一个键和值,再调用accept方法

底层源码:

public class MapDemo4 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();
​
        //添加元素
        map.put("AAA", "aaa");
        map.put("BBB", "bbb");
        map.put("CCC", "ccc");
​
        //遍历集合,内部类
        map.forEach(new BiConsumer<String, String>() {
            @Override
            public void accept(String s, String s2) {
                System.out.println(s+"="+s2);
            }
        });
​
        System.out.println("-------------------------------------------");
​
        //遍历集合,lambda表达式
        map.forEach(( s,  s2)->System.out.println(s+"="+s2));
​
    }
}

HashMap

HashMap的特点

  1. HashMap是Map里面的一个实现类

  2. 直接使用Map里面的方法就可以了

  3. 特点都是由键决定的:无序、不重复、无索引

  4. HashMap跟HashSet底层原理是一模一样的,都是哈希表结构

  5. 依赖hashcode方法和equals方法保证键的唯一

  6. 如果键存储的是自定义对象,需要重写hashcode和equals方法

  7. 如果值存储自定义对象,不需要重写hashcode和equals方法

案例

需求 创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。存储三个键值对元素,并遍历 要求:同姓名,同年龄认为是同一个学生

public class Student {
    private String name;
    private int age;
​
    public Student() {
    }
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }
​
    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }
​
    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }
​
    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }
​
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
​
    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
​
/**
 * 需求
 * 创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。存储三个键值对元素,并遍历
 * 要求:同姓名,同年龄认为是同一个学生
 */
public class MapDemo5 {
    public static void main(String[] args) {
        //创建map集合对象
        HashMap<Student,String> map = new HashMap<>();
​
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("zhangsan",23);
​
        map.put(s1,"陕西");
        map.put(s2,"山西");
        map.put(s3,"北京");
​
        map.forEach((Student student, String s)->System.out.println(student + "=" + s));
​
​
    }
}

需求 某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是A、B、C、D。每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

public class MapDemo6 {
    public static void main(String[] args) {
        //利用数组存储4个景点
        String[] strs = {"A", "B", "C", "D"};
        //利用随机数模拟80名同学投票
        ArrayList<String> list = new ArrayList<>();
        //将投票结果存入list
        Random random = new Random();
        for (int i = 0; i < 80; i++) {
            int index = random.nextInt(strs.length);
            list.add(strs[index]);
        }
​
        //统计
        HashMap<String, Integer> hashMap = new HashMap<>();
        //遍历list,将其元素存入map
        for (String s : list) {
            //如果hashmap里面已经有这个键
            //获取其值,然后加1
            if (hashMap.containsKey(s)) {
                Integer value = hashMap.get(s);
                value++;
                hashMap.put(s, value);
            } else {
                hashMap.put(s, 1);
            }
        }
        //找出最大值
        Integer max = 0;
        Set<String> set = hashMap.keySet();
        for (String s : set) {
            if (hashMap.get(s) >= max){
                max = hashMap.get(s);
            }
        }
​
        //找出那个景点,
        Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            if (entry.getValue() == max){
                System.out.println(entry.getKey());
            }
        }
​
    }
}

LinkedHashMap

由键决定:有序、不重复、无索引。 这里的有序指的是保证存储和取出的元素顺序一致 原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序,。

 

public class MapDemo7 {
    public static void main(String[] args) {
​
        LinkedHashMap<String, Integer> stringIntegerLinkedHashMap = new LinkedHashMap<>();
​
        stringIntegerLinkedHashMap.put("a",1);
        stringIntegerLinkedHashMap.put("c",3);
        stringIntegerLinkedHashMap.put("b",2);
​
        System.out.println(stringIntegerLinkedHashMap); //{a=1, c=3, b=2} 存入和取出的元素顺序一致
​
    }
}

TreeMap

TreeMap跟Treeset底层原理一样,都是红黑树结构的。 由键决定特性:不重复、无索引、可排序 可排序:对键进行排序 注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则 代码书写两种排序规则 实现Comparable接口,指定比较规则, 创建集合时传递Comparator比较器对象,指定比较规则。

TreeMap基本应用

需求1:

键:整数表示id 值:字符串表示商品名称 要求:按照id的升序排列、按照id的降序排列

public class MapDemo8 {
   public static void main(String[] args) {
      //创建集合对象,同时处传递Comparator比较器对象,指定比较规则
      TreeMap<Integer, String> treeMap = new TreeMap<>(( o1,  o2)->o2 - o1);
      //添加元素
      treeMap.put(1,"奥利奥");
      treeMap.put(9,"九个核桃");
      treeMap.put(7,"雷碧");
      treeMap.put(2,"汪汪");
      treeMap.put(3,"康帅傅");
      treeMap.put(5,"哇哈哈哈");
​
      Set<Map.Entry<Integer, String>> entries = treeMap.entrySet();
      for (Map.Entry<Integer, String> entry : entries) {
         System.out.print(entry.getKey() + entry.getValue() + " "); //9九个核桃 7雷碧 5哇哈哈哈 3康帅傅 2汪汪 1奥利奥 
      }
   }
}

 

需求2:

键:学生对象 值:籍贯 要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人。

public class Student implements Comparable<Student> {
    private String name;
    private int age;
​
    public Student() {
    }
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }
​
    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }
​
    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }
​
    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }
​
​
​
    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
​
    @Override
    public int compareTo(Student o) {
        int i = this.getAge() - o.getAge();
        i = i == 0 ? this.getName().compareTo(o.getName()) : i;
        return i;
    }
}
​
​
​
public class MapDemo9 {
    public static void main(String[] args) {
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("wangwu",25);
        Student s4 = new Student("a",23);
        Student s5 = new Student("a",23);
        
        TreeMap<Student, String> studentStringTreeMap = new TreeMap<>();
        studentStringTreeMap.put(s1,"河北");
        studentStringTreeMap.put(s2,"河南");
        studentStringTreeMap.put(s3,"北京");
        studentStringTreeMap.put(s4,"上海");
        studentStringTreeMap.put(s5,"湖南");
​
        studentStringTreeMap.forEach((Student student, String s)-> System.out.println(student + s) );
    }
}
案例

统计个数 需求:字符串“aababcabcdabcde” 请统计字符串中每一个字符出现的次数,并按照以下格式输出 输出结果: a(5)b(4)c(3)d(2)e(1)

public class MapDemo10 {
    public static void main(String[] args) {
        String str = "aababcabcdabcde";
        TreeMap<Character, Integer> tm = new TreeMap<>();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (tm.containsKey(c)) {
                Integer integer = tm.get(c);
                tm.put(c,++integer);
            }else {
                tm.put(c,1);
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        tm.forEach((Character key, Integer value) -> stringBuilder.append(key).append("(").append(value).append(")"));
        System.out.println(stringBuilder); //a(5)b(4)c(3)d(2)e(1)
    }
}

可变参数

在JDK5的时候,出现了可变参数,所谓可变参数,就是方法形参的个数是可以发生变化的 格式 : 属性类型...名字

在底层,可变参数底层就是一个数组

比如,我现在要计算n个整数的和,以前我们先创建一个数组,将整数存入数组中,然后将数组传递给求和的方法,

现在,我们不用自己创建数组了,Java会帮我们创建好

以前,需要我们自己创建数组
public class ArgsDemo {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9,10};
        System.out.println(getSum(arr));
    }
​
    public static int getSum(int[] arr){
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum;
    }
}
​
现在,利用可变参数,Java会帮我们创建数组
public class ArgsDemo {
    public static void main(String[] args) {
        System.out.println(getSum(1,2,3,4,5,6,7,8,9,10));
    }
​
    public static int getSum(int...arr){
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum;
    }
}

细节:

1.在方法的形参中最多只能写一个可变参数 2.在方法的形参当中,如果出了可变参数以外,还有其他的形参,那么可变参数要写在最后

Collections

● java.util.Collections:是集合工具类 ● 作用:Collections不是集合,而是集合的工具类

Collections常用的API

方法名称说明
public static <T> boolean addAll(Collection<T> c,T... elements)批量添加元素
public static void shuffle(List<?> list)打乱List集合元素的顺序
public static <T> void sort(List<T> list)排序
public static <T> void sort(List<T> list,Comparator <T> c)根据指定的规则进行排序
public static <T> int binarySearch(List <T> list, T key)以二分查找法查找元素
public static <T> void copy(List<T> dest,List <T> src)拷贝集合中的元素
public static <T> int fill(List<T>list, T obj)使用指定的元素填充集合
public static <T> void max/min(collection <T> coll)根据默认的自然排序获取最大/小值
public static <T> void swap(List <?> list,int i,int j)交换集合中指定位置的元素
public class CollectionsDemo {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
​
        //批量添加元素
        System.out.println("----------批量添加元素----------");
        Collections.addAll(arrayList, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
​
        System.out.println(arrayList);
        System.out.println("------------------------------");
​
        //打乱List集合元素的顺序
        System.out.println("----------打乱List集合元素的顺序----------");
        Collections.shuffle(arrayList);
​
        System.out.println(arrayList);
        System.out.println("------------------------------");
​
        //根据指定的规则进行排序 这里指定倒序
        System.out.println("----------根据指定的规则进行排序----------");
        Collections.sort(arrayList, (o1, o2) -> o2 - o1);
​
        System.out.println(arrayList);
        System.out.println("------------------------------");
​
​
        //排序 默认整数是从小到大
        System.out.println("----------排序----------");
        Collections.sort(arrayList);
​
        System.out.println(arrayList);
        System.out.println("------------------------------");
​
​
        //以二分查找法查找元素
        System.out.println("----------以二分查找法查找元素----------");
        int i = Collections.binarySearch(arrayList, 1);
​
        System.out.println(i);
        System.out.println("------------------------------");
​
        //拷贝集合中的元素
        System.out.println("----------拷贝集合中的元素----------");
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        Collections.addAll(arrayList1,0,0,0,0,0,0,0,0,0,0);
        Collections.copy(arrayList1,arrayList);
​
        System.out.println(arrayList1);
        System.out.println("------------------------------");
​
​
    }
}

案例

自动点名器1

班级里有N个学生,实现随机点名器。

public class Test1 {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> arrayList = new ArrayList<>();
        //添加元素
        Collections.addAll(arrayList,"赵一","钱二","孙三","李四","周五","吴六","郑七","王八","冯九","陈十");
​
        //随机1
        Random random = new Random();
        System.out.println(arrayList.get(random.nextInt(arrayList.size())));
​
        //随机2
        Collections.shuffle(arrayList);
        System.out.println(arrayList.get(0));
    }
}

自动点名器2

班级里有N个学生,实现随机点名器。 要求: 70%的概率随机到男生 30%的概率随机到女生

public class Test1 {
    public static void main(String[] args) {
        //创建集合
        ArrayList<Integer> arrayList = new ArrayList<>();
        //添加元素
        Collections.addAll(arrayList,1,1,1,1,1,1,1,0,0,0);
        
        //随机2
        Collections.shuffle(arrayList);
        Integer index = arrayList.get(0);
​
        ArrayList<String> boy = new ArrayList<>();
        ArrayList<String> girl = new ArrayList<>();
​
        Collections.addAll(boy,"赵一","钱二","孙三","李四","周五","吴六","郑七","王八","冯九","陈十");
        Collections.addAll(girl,"赵女","钱女","孙女","李女","周女");
​
        if (index == 1){
            Collections.shuffle(boy);
            System.out.println(boy.get(0));
        }else {
            Collections.shuffle(girl);
            System.out.println(girl.get(0));
        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值