Java集合

第一节

一、集合框架的学习方式

1、学习顶层:

​ 学习顶层接口/抽象类中共性的方法,所有的子类都可以使用

2、使用底层:

​ 底层不是接口就是抽象类,无法创建对象使用,需要使用底层的子类创建对象使用

Collection接口

定义的是所有单列集合中共性的方法

所有的单列集合都可以使用共性的方法

没有带索引的方法

List接口

(是单列集合的一种)

​ 1、有序的集合(存储和取出元素顺序相同)

​ 2、允许存储重复的元素

​ 3、有索引,可以使用普通的for循环遍历

List接口中有以下子类:ArrayList(重点) LinkedList(次之) Vector(了解)

ArrayList:底层是数组实现的,查询快,增删慢

LinkedList:底层是链表实现的,查询慢,增删快

Set接口

(是单列集合的一种)

​ 1、不允许存储重复的元素、存取无序

​ 2、没有索引(不能使用普通的for循环遍历)

Set接口中有一下子类:HashSet(重点) LinkedHashSet(次之) TreeSet(了解)

HashSet:底层是哈希表+(红黑树)实现的,无索引、不可以存储重复元素,存取无序

LinkedHashSet:底层是哈希表+链表实现的,无索引,不可以存储重复元素,可以保证存取顺序

TreeSet:底层是二叉树实现。一般用于排序

二、Iterator迭代器

java.util.Iterator接口:迭代器(对集合进行遍历)

有两个常用的方法

​ boolean hasNext() 如果仍有元素可以迭代,则返回true。(判断集合中还有没有下一个元素,有就返回true,没有就返回false)

​ E next() 返回迭代的下一个元素。(取出集合中下一个元素)

Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊。Collection接口中有一个方法叫iterator(),这个方法返回的就是迭代器的实现类对象

​ Iterator iterator() 返回在此collection的元素上进行迭代的迭代器

迭代器的使用步骤:

​ 1、使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)

​ 2、使用iterator接口中的方法hasNext判断还有没有下一个元素

​ 3、使用iterator接口中的方法next取出集合中的下一个元素

增强for循环

增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合,它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作

格式

for(元素的数据类型 变量名 :Collection集合名or数组名){

​ //写操作代码

​ sout(变量名);

}

三、泛型

泛型:是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型

泛型也可以看成是一个变量,用来接收数据类型

​ E e:Element 元素

​ T t:Type 类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mexAZx8R-1615820935369)(D:\Program Files\java笔记\Java自我小结\linux\泛型.PNG)]

定义含有泛型的类

定义格式:

修饰符 class 类名<代表泛型的变量泛型>{ }

定义含有泛型的方法

定义格式:

修饰符 <代表泛型的变量> 返回值类型 方法名称(参数){ }

定义含有泛型的接口

定义格式:

修饰符 interface 接口名<代表泛型的变量>{ }

含有泛型的接口,第一种方式:定义接口的实现类,实现接口,指定接口的泛型

public class GenericInterfaceImpl implements GenericInterface{

​ @Override

​ …

}

含有泛型的接口,第二种方式:接口时是什么泛型实现类就是什么泛型,类跟着接口走。就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型

public class GenericInterfaceImpl implements GenericInterface {

​ @Override

​ …

}

泛型通配符

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用

通配符基本使用

泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

此时只能接收数据(只能作为方法的参数传递),不能往该集合中存储数据

详细代码见:D:\Learn\javaAgain\src\year21Month01\Month01Day12\GenericClass\GenericDemo02.class 文件

泛型的上限限定和下限限定
泛型的上限限定:? extends E 代表使用的泛型只能是E类型的子类/本身
泛型的上限限定:? super E 代表使用的泛型只能是E类型的父类/本身

集合综合案例

斗地主案例:
package year21Month01.Other.斗地主案例;

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;

/**
 * @Author:pp
 * @Date:2021/1/16 16:00
 */
public class DouDiZhu {
    public static void main(String[] args) {
        //1、准备排
        //1.1首先准备一个集合用来存储54张牌
        ArrayList<String> poker = new ArrayList<>();

        //2、准备两个集合分别用来存储花色和序号
        String [] color = {"♥","♣","♦","♠"};
        String [] number = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};

        //3、将大王小王放入poker中
        poker.add("大王");
        poker.add("小王");

        //4、将花色和序号匹配,用一个嵌套for循环,并将匹配好的放入集合poker中
        for (String c:color) {
            for (String n:number){
                poker.add(c+n);
            }
        }
        //5、洗牌
        //5.1运用collections中的shuffle方法。
        Collections.shuffle(poker);
        System.out.println(poker);

        //6、发牌
        //6.1首先要准备四个集合,分别用来存放玩家的牌和剩余的三张底牌
        ArrayList<String> play01 = new ArrayList<>();
        ArrayList<String> play02 = new ArrayList<>();
        ArrayList<String> play03 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();

        //6.2首先将扑克中的牌取出来,再进行分发
        for (int i = 0; i < poker.size(); i++) {
            String p = poker.get(i);
            //进行判断底牌的分发,如果不先进行底牌分发。直接进行玩家分发,到时候是没有底牌的
            if (i>=51){
                dipai.add(p);
            }else if (i%3==0){
                play01.add(p);
            }
            else if (i%3==1){
                play02.add(p);
            }
            else if (i%3==2){
                play03.add(p);
            }
        }
        //7、看牌
        System.out.println("玩家01:"+play01);
        System.out.println("玩家02:"+play02);
        System.out.println("玩家03:"+play03);
        System.out.println("底牌:"+dipai);
    }

}

第二节

一、常见的数据结构

数据存储的常用结构有:栈、队列、数组、链表和红黑树

·栈:Stack,又称为栈它是运算受限的线性表,其限制是仅允许在表的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作

简单的说:采用该结构的集合,对元素的存取有如下的特点:

1、先进后出(即,存进去的元素,要在它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能取出下面的子弹

2、栈的入口、出口都是栈的顶端位置

队列

·队列:queue,简称队,它同栈一样,也是一种运算受限的线性表,其限制是允许在表的一端进行插入,而在表的另一端进行删除

简单的说:采用该结构的集合,对元素的存取有如下特点:

1、先进先出(即,存进去的元素要在它前面的元素依次取出后,才能取出该元素)。例如,小火车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来

2、队列的入口、出口各占一侧

数组

·数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。

简单的说:采用该结构的集合,对元素的存取有如下的特点:

1、查找速度快:通过索引,可以快速访问指定位置的元素

2、增删元素慢

​ 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。

链表

·链表 :linked list,由一系列节点node(链表中每一个元素称为节点),节点在运行时可以动态生成,每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。我们常说的链表结构有单向链表与双向链表,那么这里给大家介绍的是单向链表。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o98YDIOF-1615820935372)(D:\Program Files\java笔记\Java自我小结\linux\单向链表.PNG)]

简单的说,采用该结构的集合,对元素的存取有如下的特点:

1、多个节点之间,通过地址进行链接。例如,多个人手拉手,每个人使用自己的右手拉住下一个人的左手,依次类推,这样多个人就连在一起了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n66hu9Bq-1615820935373)(D:\Program Files\java笔记\Java自我小结\linux\单向链表1.PNG)]

2、查找元素慢:想查找某个元素,需要通过连接的节点,一次向后查找指定元素(每次查询都必须从头开始查询)

3、增删元素快

​ ·增加元素:只需要修改连接下个元素的地址即可

单向链表:链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序有可能不一致)

双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合

红黑树

(特点:趋近于平衡树,查询的速度非常快,查询叶子节点最大次数和最小次数不能超过2倍)

·二叉树:binary tree,是每个节点不超过2的有序树(tree)

简单的理解:就是一种类似于我们生活中树的结构,只不过每个节点上都最多只能有两个子节点。

二叉树是每个节点最多有两个子树的结构,顶上的叫根节点,两边被称作“左子树”和“右子树”

·查找树/排序树

在二叉树的基础上,元素是有大小顺序的

左子树小,右子树大

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BI7Fwj54-1615820935375)(D:\Program Files\java笔记\Java自我小结\linux\排序树.PNG)]

第三节 List集合

一、List接口介绍

java.util.List接口继承自Collection接口,是单列集合的一个重要分支,习惯性地会将实现了List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

List接口的特点:

1、它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的。

2、它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)

3、集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素

二、ArrayList集合

java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合

三、LinkedList集合

java.util.LinkedList集合数据存储的结构是链表结构。方便元素增加、删除的集合

LinkedList是一个双向链表(实际开发中对一个集合元素的添加与删除经常涉及到首位操作)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L4EjQQOL-1615820935377)(D:\Program Files\java笔记\Java自我小结\linux\LinkedList.PNG)]

第四节 Set接口

一、HashSet集合介绍

java.util.Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格。与List接口不同的是,Set接口中元素无序,并且都会以某种规则保证存入的元素不重复。

Set集合有多个子类,这里我们介绍其中的java.util.HashSet、java.util.LinkedHashSet这两个集合。

注释:Set集合取出元素的方式可以采用:迭代器、增强for。

java.util.HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持,

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因为具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCode与equals方法

二、HashSet集合存储数据的结构(哈希表)

什么是哈希表?

在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查询时间。

简单的说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的

set集合存储元素不重复的元素(例,存储自定义类型的元素:Person、Student)

前提:存储的元素必须重写hashCode方法和equals方法。比较方式:首先比较hashCode值是否相同,不同则在对应数组中hashCode值中存储元素。若相同,再比较equals方法,若相同则不进行存储,若不同则在对应数组中hashCode值中存储元素

三、LinkedHashSet集合

/**
 * java.util.LinkedHashSet集合 extends    HashSet集合
 * LinkedHashSet集合的特点:
 *  底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序)
 *  保证元素有序
*/

四、可变参数

/**
VarArgs可变参数 (数据类型...变量名)

可变参数是JDK1.5以后出现的新特性
使用前提:
    当方法的参数列表数据类型已经确定,但是参数个数不确定,就可以使用可变参数

 使用格式:
 修饰符  返回值类型    方法名(数据类型...变量名){}

 可变参数的原理:
    可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
    传递的参数可以是0个(不传递)或多个
* */
public class Demo04VarArgs {
    public static void main(String[] args) {
        int result = add(10, 20);
        System.out.println(result);
    }
    /*
    可变参数的注意事项:
    		1、一个方法的参数列表,只能有一个可变参数 (错误写法:int...a,double...c)
    		2、如果方法的参数列表有多个,那么可变参数必须写在参数列表的末尾(int a,double b,int...c)
    */
    
    //可变参数的特殊(终极)写法
    public static void method(Object...obj){}
    
    /**
     * 定义一个方法,计算(0-n)整数的和
     * 已知:计算的是和,数据类型已经确定,但是传递的参数不确定,则可以使用可变参数
    */
    private static int add(int...arr) {
        int sum = 0 ;
        for (int i:arr) {
            sum+=i;
        }
        return sum;
    }
}

第五节 Collections

一、常用方法介绍

java.util.Collections是集合工具类,用来对集合进行操作

·public static boolean addAll(Collection c,T…elements):往集合中添加一些元素

·public static void shuffle(List<?> list)打乱顺序:打扰集合顺序

·public static void sort(List list):将集合中元素按照默认规则排序

.public static void sort(List list,Comparator <? super T):将集合中元素按照指定规则排序

public class Demo01Collections {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"a","b","c","d","e");
//        System.out.println(list);
//        Collections.shuffle(list);
//        Collections.sort(list);

 /**
  * -java.util.Collections是集合工具类,用来对集合进行操作。部分方法如下:
  *     public static <T> void  sort(List<T>  list):将集合中元素按照默认规则排序
  *
  * 注意:
  *     sort(List<T> list)使用前提:
  *     被排序的集合里边存储的元素,必须实现comparable接口,重写接口中的方法compareTo定义排序规则
  
  Comparable接口的排序规则:
  	自己(this)-参数:升序
 */

        ArrayList<Person> list01 = new ArrayList<>();
        list01.add(new Person("张三",20));
        list01.add(new Person("李四",16));
        list01.add(new Person("王五",13));
        System.out.println(list01);
        Collections.sort(list01);
        System.out.println(list01);
        //作为扩展:了解
        ArrayList<Student> list02 = new ArrayList<>();
        Student s1 = new Student("b迪丽热巴",18);
        Student s2 = new Student("古力娜扎",20);
        Student s3 = new Student("马儿扎哈",13);
        Student s4 = new Student("a迪丽热巴",18);
        list02.add(s1);
        list02.add(s2);
        list02.add(s3);
        list02.add(s4);
        System.out.println(list02);

        Collections.sort(list02, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //按照年龄升序
                int result = o1.getAge()-o2.getAge();
                //如果年龄相同,再使用姓名第一个字进行比较
                if (result==0){
                    result = o1.getName().charAt(0)-o2.getName().charAt(0);
                }
                return result;
            }
        });
        System.out.println(list02);

    }
}

sort两种比较方法:
	1、类实现Comparable接口,重写CompareTo方法
	2、主函数中调用Collections.sort方法,new Comparator<T>(){}

第六节 Map集合

一、概述

现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号和个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Maps接口

·Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储

·Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键和值两部分组成,通过键可以找所对应的值

·Collection中的集合称为单列集合,Map中的集合称为双列集合。

·需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值

二、Map集合的特点

1、Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)

2、Map集合中的元素,key和value的数据类型可以相同,可以不同

3、Map集合中的元素,key是不允许重复的,value是可以重复的

4、Map集合中的元素,key和value是一一对应的

三、Map常用子类

主要讲解常用的HashMap集合、LinkedHashMap集合

·HashMap<K,V>:存储数据采用的是哈希表结构(查询速度非常快-数组+单向列表/红黑树(阈值>8)),元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法

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

HashMap是一个无序的集合,存储元素和取出元素的顺序有可能不一致

·LinkedHashMap<K,V>:HashMap下有一个子类LinkedHashMap,存储数据采用的是哈希表结构+链表结构(保证迭代的顺序)。通过链表结构可以保证元素的存取顺序一致;通过哈希结构可以保证键的唯一、不重复,需要写键的hashCode()方法、equals()方法

LinkedHashMap集合是一个有序的集合,存储和取出元素的顺序是一致的

tips:Map接口中的集合有两个泛型变量<K,V>,在使用时,要为两个泛型变量赋值数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同

四、Map接口中的常用方法

·public V put (K key,V value):把指定的键与指定的值添加到Map集合中

·public V remove(Object key):把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值

·public V get(Object key):根据指定的键,在Map集合中获取对应的值

·boolean containsKey(Object key):判断集合中是否包含指定的键

·public Set keySet():获取Map集合中所有的键,存储到Set集合中

·public Set<Map.Entry<K,V>> extrySet():获取到Map集合中所有的键值对对象的集合(Set集合)

public class Demo01Map {
    public static void main(String[] args) {

        show04();
    }
/**
 * boolean containsKey(Object key):判断集合中是否包含指定的键
 * 包含返回true     不包含返回false
*/
    private static void show04() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        //向集合中添加元素
        map.put("李前",18);
        map.put("田磊",18);
        map.put("陈恒宇",18);
        map.put("谢春雨",18);
//        判断集合中是否包含指定的键
        boolean b1 = map.containsKey("田磊");
        System.out.println(b1);
    }
    /**
     * public  V  get(Object key):根据指定的键,在Map集合中获取对应的值
     * 返回值v:
     *  key值存在,v返回获取到的值
     *  key值不存在,v返回null
    */
    private static void show03() {
        //创建Map集合对下不过
        Map<Integer,String> map = new HashMap<>();
        //向集合中添加元素
        map.put(2410,"田磊");
        map.put(2411,"谢春雨");
        map.put(2412,"陈恒宇");
        map.put(2413,"李前");
        System.out.println(map);
        //通过指定的键来获取对应的值
        String v1 = map.get(2410);
        //田磊
        System.out.println(v1);
        String v2 = map.get(2416);
        //null
        System.out.println(v2);
    }
    /**
 * public  V  remove(Object  key):
 * 把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值
 * 返回值V:
 *  key存在,v返回被删除的值
 *  key不存在,v返回null
*/
    private static void show02() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        //向集合中添加元素
        map.put("李前",168);
        map.put("田磊",169);
        map.put("谢春雨",175);
        System.out.println(map);
        //通过指定的键删除在Map集合中对应的键值对
        Integer v1 = map.remove("李前");
        System.out.println(v1);
        Integer v2 = map.remove("李前");
        System.out.println(v2);
        System.out.println(map);
    }

    /**
 * //public    V  put    (K key,V value):把指定的键与指定的值添加到Map集合中
 * 返回值V:
 *  存储键值对的时候,key不重复,V值返回的是null
 *  存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
*/
    private static void show01() {
        //创建Map集合对象,多态
        Map<String,String> map = new HashMap<>();

        String p1 = map.put("张三", "张是");
        System.out.println(p1);
        String p2 = map.put("张三", "张v");
//        System.out.println(p2);
        map.put("2410","李前");
        map.put("2411","田磊");
        map.put("2412","田磊");
        System.out.println(map);
    }
}

五、Map集合遍历键找值方式

键找值方式:即通过元素中的键,获取键所对应的值

分析步骤:

1、获取Map集合中所有的键,由于键是唯一的所以返回一个Set(不允许存储重复的元素)集合存储所有的键。方法提示:keySet()

2、遍历键的Set集合,得到每一个键

3、根据键,获取键所对应的值。方法提示:get(K key)

代码演示:

public class Demo02KeySet {
    public static void main(String[] args) {
        //创建Map集合对象,多态
        Map<String,Integer> map = new HashMap<>();
        //向集合中添加元素
        map.put("田磊",168);
        map.put("李前",158);
        map.put("写春雨",178);
        //1、使用Map集合中的keySet()方法,把Map集合中所有的key取出来,存放到set集合中
        Set<String> set = map.keySet();
        //当然也可以获取迭代器的方法
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3、通过调用Map集合的get(Object key)方法,通过key找到value
            Integer values = map.get(key);
            System.out.println(key+"="+values);
        }
        System.out.println("================================");
        //2、遍历set集合,获取Map集合中所有的key
        for (String key:set) {
            //3、通过调用Map集合的get(Object key)方法,通过key找到value
            Integer values = map.get(key);
            System.out.println(key+"="+values);
        }
    }
}

六、Entry键值对对象

我们已经知道,Map集合中存放的是两种对象,一种称为key(键),一种称为value(值),它们在Map集合中是一一对应的关系,这一对对象又称做Map中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。

既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值的方法:

·public K getKey():获取Entry对象中的键

·public V getValue():获取Entry对象中的值

七、Map集合遍历键值对方式

Map.Entry<K,V>:在Map接口中有一个内部接口Entry

作用:当Map集合一创建,那么就会在Map集合中创建一个Entry对象,用来记录键与值(键值对对象,键与值的映射关系)—>结婚证

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iCf3mEIG-1615820935378)(D:\Program Files\java笔记\Java自我小结\linux\Entry.PNG)]

代码演示:

/**
 * Map集合遍历的第二种方式:使用Entry对象遍历
 * Map集合中的方法:
 *   Set<Map.Entry<K,V>> entrySet()返回此映射中包含的映射关系的 Set 视图。
 *实现步骤:
 * 1、使用Map集合中的entrySet()方法,把Map集合中的多个Entry对象存储到一个set集合中
 * 2、遍历set集合,获取Entry对象
 * 3、使用Entry对象的getKey()和getValue()方法,获取键与值
*/
public class Demo03EntrySet {
    public static void main(String[] args) {
//创建Map集合对象,多态
        Map<String,Integer> map = new HashMap<>();
        //向集合中添加元素
        map.put("田磊",168);
        map.put("李前",158);
        map.put("写春雨",178);
        //1、使用Map集合中的entrySet()方法,把Map集合中的多个Entry对象存储到一个set集合中
        Set<Map.Entry<String, Integer>> set = map.entrySet();
        //2、遍历set集合,获取Entry对象
        //使用迭代器遍历
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while (it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            //3、使用Entry对象的getKey()和getValue()方法,获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
        System.out.println("==============================");
        //使用增强for循环遍历
        for (Map.Entry<String,Integer> entry: set){
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
    }
}

八、HashMap存储自定义类型键值

代码演示:

/**
 * HashMap存储自定义类型键值
 * Map集合保证key是唯一的:
 *  作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一
*/
public class HashMapSavePerson {
    public static void main(String[] args) {
        show02();
    }
/**
 * HashMap存储自定义类型键值
 * key:Person类型
 * Person类必须重写hashCode方法和equals方法,才可以保证唯一性
 * value:String类型
 * value可以重复(同名同年龄视为同一个人)
 *
*/
    private static void show02() {
        //创建HashMap集合
        HashMap<Person,String> map = new HashMap<>();
        //向集合中添加元素
        map.put(new Person("田磊",18),"2410");
        map.put(new Person("李前",19),"2410");
        map.put(new Person("谢春雨",18),"2410");
        map.put(new Person("田磊",18),"2410");
        //使用Map集合的entrySet方法和增强for循环遍历集合
        Set<Map.Entry<Person, String>> set = map.entrySet();
        for (Map.Entry<Person, String> entry : set) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"----->"+value);
        }

    }

    /**
     * HashMap存储自定义类型键值
     * key:String类型
     * String类型重写了hashCode方法和equals方法,可以保证唯一性
     * value:person类型
     * value可以重复(同名同年龄视为同一个人)
    */
    private static void show01() {
        //创建一个HashMap集合
        HashMap<String, Person> map = new HashMap<>();
        map.put("北京",new Person("田磊",18));
        map.put("上海",new Person("谢春雨",19));
        map.put("广州",new Person("李前",20));
        map.put("北京",new Person("田磊",18));
        //是使用keySet方法和增强for循环遍历集合
        Set<String> set = map.keySet();
        for (String key : set) {
            Person value = map.get(key);
            System.out.println(key+"----->"+value);
        }

    }
}

九、LinkedHashMap

java.util.LinkedHashMap<K,V> extends HashMap<K,V>

Map接口的哈希表和链接列表实现的,具有可预知的迭代顺序

底层原理:

哈希表+链表(记录元素顺序)

十、HashTable

/**
 * java.util.hashTable<K,V> implements  Map<K,V>
 *     HashTable:底层也是哈希表,是一个线程安全的集合,是单线程集合,速度慢
 *     HashMap:底层是哈希表,是一个线程不安全的集合,是多线程集合,速度快
 *
 *     HashMap集合(之前学的所有集合):可以存储null值和null键
 *     HashTable集合不能存储null值和null键
 *
 *     HashTable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap和ArrayList)取代了
 *     HashTable的子类Properties依然活跃在历史舞台
 *     Properties集合是一个唯一和IO流相结合的集合
*/

十一、集合练习

代码演示:

/**
 * 练习:计算一个字符串中每个字符出现的次数
 *
 * 分析:
 *  1、使用Scaner获取用户输入的字符串
 *  2、创建Map集合,key是字符串中的字符,value是字符出现的个数
 *  3、遍历字符串,获取每一个字符
 *  4、使用获取到的字符,去Map集合判断key是否存在
 *      key存在
 *          通过字符(key),获取value(字符个数)
 *          value++
 *          put(key,value)把新的value存储到Map集合中
 *      key不存在
 *          put(key,1)
 *5、遍历Map集合,输出结果
*/
public class Test01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入字符串:");
        String str = sc.next();
        HashMap<Character,Integer> map = new HashMap<>();
        for (char key : str.toCharArray()) {
            if (map.containsKey(key)){
                Integer value = map.get(key);
                value++;
                map.put(key,value);
            }else {
                map.put(key,1);
            }
        }
        Set<Character> set = map.keySet();
        for (Character key : set) {
            Integer value = map.get(key);
            System.out.println(key+"----->"+value);
        }
    }
}

第七节 知识点补充

一、Debug追踪

使用idea的断点调式功能,查看程序的运行过程

Debug调式程序:

​ 可以让代码逐行执行,查看代码执行的过程,调式程序中出现的bug

使用方式:

​ 在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里)

​ 右键,选择Debug执行程序

​ 程序就会停留在添加的第一个断点处

执行程序(控制台中也可看到):

​ f8:逐行执行程序

​ f7:进入到方法中

​ shift+f8:跳出方法

​ f9:跳到下一个断点,如果没有下一个断点,那么就结束程序

ctrl+f2:退出debug模式,停止程序

Console:切换到控制台

第八节 模拟斗地主洗牌发牌

代码演示:

/**
 * 斗地主综合案例:有序版本
 * 1、准备牌
 * 2、洗牌
 * 3、发牌
 * 4、排序
 * 5、看牌
*/
public class DouDiZhu {
    public static void main(String[] args) {
        //1、准备牌
        //创建一个Map集合,存储牌的索引和组装好的牌
        HashMap<Integer,String> poker = new HashMap<>();
        //创建一个list集合,存储牌的索引
        ArrayList<Integer> pokerIndex = new ArrayList<>();
        //定义两个集合分别存储牌的花色和牌的序号
        ArrayList<String> colors = new ArrayList<>();
        ArrayList<String> numbers = new ArrayList<>();
        //将牌的花色和牌的序号添加到集合中
        Collections.addAll(colors,"♥","♠","♦","♣");
        Collections.addAll(numbers,"2","A","K","Q","J","10",
                "9","8","7","6","5","4","3");
        //把大王小王存放到集合中
        //定义一个牌的索引
        int index = 0;
        poker.put(index,"大王");
        pokerIndex.add(index);
        index++;
        poker.put(index,"小王");
        pokerIndex.add(index);
        index++;
        //循环嵌套遍历两个集合,组装52张牌,存储到集合中
        for (String number:numbers){
            for (String color:colors){
                poker.put(index,color+number);
                pokerIndex.add(index);
                index++;
            }
        }
        //2、洗牌
        //使用Collections中的shuffle方法
        Collections.shuffle(pokerIndex);
        //3、发牌
        //定义4个集合,存储玩家牌的索引和底牌的索引
        ArrayList<Integer> play01 = new ArrayList<>();
        ArrayList<Integer> play02 = new ArrayList<>();
        ArrayList<Integer> play03 = new ArrayList<>();
        ArrayList<Integer> diPai = new ArrayList<>();
        //遍历存储牌索引的List集合,获取每一个牌的索引
        for (int i = 0; i < pokerIndex.size(); i++) {
            Integer in = pokerIndex.get(i);
            //先判断底牌
            if (i>=51){
                diPai.add(in);
            }
            else if (i%3==0){
                play01.add(in);
            }
            else if (i%3==1){
                play02.add(in);
            }
            else if (i%3==2){
                play03.add(in);
            }
        }
        /**
         * 4、排序
         * 使用Collection中的方法sort(list)
         * 默认是升序排序
        */
        Collections.sort(play01);
        Collections.sort(play02);
        Collections.sort(play03);
        Collections.sort(diPai);


        //看牌
        //调用看牌的方法
        lookPoker("田磊",poker,play01);
        lookPoker("李前",poker,play02);
        lookPoker("谢春雨",poker,play03);
        lookPoker("底牌",poker,diPai);
    }
    /**
     * 定义一个看牌的方法,提高代码的复用性
     * 参数:
     *  String name:玩家名称
     *  HashMap<Integer,String> poker:存储牌的集合
     *  ArrayList<Integer> list:存储玩家和底牌的List集合
     *
     *  查表法:
     *      遍历玩家或底牌集合,获取牌的索引
     *      使用牌的索引去Map集合中找对应的牌
     */
    public static void lookPoker(String name,HashMap<Integer,String> poker,ArrayList<Integer> list){
        //输出玩家名称,不换行
        System.out.print(name+": ");
        //遍历玩家或底牌集合,获取牌的索引
        for (Integer key:list){
            //使用牌的索引去Map集合中找对应的牌
            String value = poker.get(key);
            System.out.print(value+" ");
        }
        //打印完每一个玩家的牌,然后换行
        System.out.println();
        }
    }

更详细代码见:

D:\Learn\javaAgain\src\year21Month01\Other\斗地主案例02\exercese01.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值