java的第十四天

01、Iterator迭代器

目标:学习使用迭代器获取集合中的数据

讲解:

1.为什么要迭代器:

​ List接口有索引,我们可以通过for循环+get方法来获取数据,但是Set接口这边没有索引,不能通过for循环 +get方式获取数据.
​ Collection接口就搞了一种通用的方式方便所有的集合来获取数据,就是迭代器(Iterator)

2.什么是迭代:(过程)

​ 迭代是取数据的过程.先判断集合中是否有数据,如果有,就取出一个数据,接着再判断集合中是否有数据,
​ 如果有再接着取出一个数据,这样往复循环直到所有数据都取出来了.

3.迭代器的常用方法:

​ interface Iterator {
​ boolean hasNext() 判断是否有下一个元素,如果有返回true
​ E next() 返回下一个元素
​ }

4.迭代器和集合的关系:

​ Collection接口中有一个方法可以得到迭代器

​ interface Collection {
​ Iterator iterator() 返回此集合中元素的迭代器
​ }

​ interface List extends Collection {
​ }

​ class ArrayList implements List {
​ pulic Iterator iterator() {
​ return new 迭代器();
​ }
​ }

​ 每个集合都会实现iterator方法,都能获取到迭代器

5.如何获取迭代器:(重点)

​ 集合.iterator();

小结:

1.迭代器的使用步骤?
1.得到迭代器 Iterator itr = list.iterator();
2.循环判断是否有下一个 while (itr.hasNext()) { }
3.如果有,就取出下一个 itr.next()

小贴士:
  1. 在进行集合元素获取时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会抛出
    java.util.NoSuchElementException没有集合元素异常。
  2. 在进行集合元素获取时,如果添加或移除集合中的元素 , 将无法继续迭代 , 将会抛出
    ConcurrentModificationException并发修改异常
课堂代码:
import java.util.ArrayList;
import java.util.Iterator;
public class Demo01 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("马蓉");
        list.add("李小璐");
        list.add("白百合");
        list.add("张柏芝");

        // 使用迭代器来获取集合的元素
        // 1.得到迭代器
        // Iterator<String> itr = list.iterator();

        // 获取元素
        // System.out.println(itr.next());
        // System.out.println(itr.next());
        // System.out.println(itr.next());
        // System.out.println(itr.next());
        // System.out.println(itr.next()); // NoSuchElementException: 没有元素异常

        // 先判断,再取出
        // if (itr.hasNext()) {
        //     System.out.println(itr.next());
        // }
        //
        // if (itr.hasNext()) {
        //     System.out.println(itr.next());
        // }
        //
        // if (itr.hasNext()) {
        //     System.out.println(itr.next());
        // }
        //
        // if (itr.hasNext()) {
        //     System.out.println(itr.next());
        // }
        //
        // if (itr.hasNext()) {
        //     System.out.println(itr.next());
        // }

        // 以上代码都是重复代码, 我们可以改成循环
        // 1.得到迭代器
        Iterator<String> itr = list.iterator();
        // 2.循环判断是否有下一个元素
        while (itr.hasNext()) {
            // 3.如果有,就取出下一个元素
            System.out.println(itr.next());
        }
    }

    private static void test01() {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(110);
        list.add(119);
        list.add(120);

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i)); // 根据索引去获取数据
        }
    }
}

02、迭代器的实现原理

目标:理解迭代器的实现原理

讲解:

​ 我们在之前案例已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素出,否则说明已到达了集合末尾,停止遍历元素。
​ Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理

[外链图片转存失败(img-r6yszUt5-1563546017461)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563447472219.png)]

迭代器迭代注意事项:

​ 一次hasNext判断,我们就取一次数据

小结:

​ 1.Iterator的hasNext()作用?
​ 判断是否有下一个元素,如果有返回true

​ 2.Iterator的next()作用?
​ 1.取出下一个元素
​ 2.将指针移动到下一个位置

课堂代码:
import java.util.ArrayList;
import java.util.Iterator;
public class Demo02 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("马蓉");
        list.add("李小璐");
        list.add("白百合");
        list.add("张柏芝");
        list.add("阿娇");
        // "马蓉", "李小璐", "白百合", "张柏芝", "阿娇"
        //      ↑

        Iterator<String> itr = list.iterator();
        while (itr.hasNext()) {
            System.out.println("next1" + itr.next()); // next1马蓉    next1白百合    next1阿娇
            // System.out.println("next2" + itr.next()); // next2李小璐    next2张柏芝
        }
    }
}

03、增强for循环

目标:学习增强for循环和增强for循环的底层

讲解:

1.什么是增强for循环:

​ JDK1.5推出的新特性.foreach循环,高级for循环

2.增强for格式:

​ for (数据类型 变量名 : 数组或集合) {
​ }

3.增强for好处:

​ 代码简单

4.增强for缺点:

​ 没有索引

5.什么时候使用增强for?

​ 如果不关心索引就可以使用增强for

小结:

​ 1.增强for循环格式?
​ for (元素的类型 变量名 : 数组或集合) {
​ }

​ 2.增强for循环好处?
​ 代码简单

小结:

增强for循环的底层
1.遍历数组,底层是普通for
2.遍历集合,底层是迭代器

课堂代码:
import java.util.ArrayList;
public class Demo03 {
    public static void main(String[] args) {
        int[] arr = new int[] {11, 22, 33};
        // 使用增强for遍历数组,底层是普通for循环
        for (int num : arr) {
            System.out.println(num);
        }

        System.out.println("------------");
        ArrayList<Integer> list = new ArrayList<>();
        list.add(110);
        list.add(119);
        list.add(120);

        // 使用增强for遍历集合,底层使用的是迭代器
        for (Integer num : list) {
            System.out.println(num);
        }

        // 增强for快捷键: 数组或集合.for

    }

    private static void test01() {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(110);
        list.add(119);
        list.add(120);

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i)); // 根据索引去获取数据
        }
    }

    private static void test02() {
        int[] arr = new int[] {11, 22, 33};

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]); // 根据索引去获取数据
        }
    }
}

04、斗地主案例

斗地主案例步骤:

1.创建一副牌

​ 1.定义牌类
​ 2.创建集合,用于保存一副牌
​ 3.使用循环生成这副牌

​ 牌可以设计为一个ArrayList,每个字符串为一张牌。 每张牌由花色数字两部分组成,我们可以使用花色集 合与数字集合嵌套迭代完成每张牌的组装。 牌由Collections类的shuffle方法进行随机排序

2.洗牌

​ 将牌的顺序打乱

3.发牌

​ 1.定义3个集合表示3个玩家
​ 2.定义一个集合表示底牌
​ 3.交替发牌

​ 将每个人以及底牌设计为ArrayList,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌

4.看牌

​ 直接打印每个集合。

课堂代码:
// 1.定义牌类
public class Poker {
    private String color;
    private String number;

    public Poker() {
    }

    public Poker(String color, String number) {
        this.color = color;
        this.number = number;
    }

    @Override
    public String toString() {
        return color + number;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}

import java.util.ArrayList;
import java.util.Collections;
public class Demo04 {
    public static void main(String[] args) {
        // 1.创建一副牌
        //     1.定义牌类
        //     2.创建集合,用于保存一副牌
        ArrayList<Poker> pokers = new ArrayList<>();

        //     3.使用循环生成这副牌
        pokers.add(new Poker("大?", ""));
        pokers.add(new Poker("小?", ""));

        String[] colors = new String[] {"♠", "♥", "♣", "♦"};
        String[] numbers = new String[] {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};

        // 一个数字要和所有花色组合
        for (String number : numbers) {
            // 2, A
            for (String color : colors) {
                // "♠", "♥", "♣", "♦"
                Poker poker = new Poker(color, number);
                pokers.add(poker);
            }
        }

        // 打印集合,看生成的一副牌
        System.out.println(pokers);

        // 2.洗牌
        //         将牌的顺序打乱
        // Collections类:
        // public static void shuffle(List<?> list): 将指定的集合中的元素随机交换位置
        Collections.shuffle(pokers);

        System.out.println("洗牌后: " + pokers);

        // 3.发牌
        //     1.定义3个集合表示3个玩家
        ArrayList<Poker> player01 = new ArrayList<>();
        ArrayList<Poker> player02 = new ArrayList<>();
        ArrayList<Poker> player03 = new ArrayList<>();
        //     2.定义一个集合表示底牌
        ArrayList<Poker> diPai = new ArrayList<>();

        /*
                3.交替发牌
              0   1    2    3    4   5   6    7    8   9   10  ...            51   52  53
            [♦4, ♠Q, ♣10, ♠A, ♥2, ♠3, ♠K, ♠10, ♥J, ♦9, ♦5, ♦2, 大?, ♣8, ♥10, ♦A, ♣]
                    根据索引发牌,规律
            玩家1:    0,3,6       索引 % 3 == 0
            玩家2:    1,4,7       索引 % 3 == 1
            玩家3:    2,5,8       索引 % 3 == 2
         */
        for (int i = 0; i < pokers.size(); i++) {
            // i是索引
            // poker是i索引对应的牌
            Poker poker = pokers.get(i);
            if (i >= 51) {
                diPai.add(poker);
            } else if (i % 3 == 0) { // 玩家1
                player01.add(poker);
            } else if (i % 3 == 1) { // 玩家2
                player02.add(poker);
            } else if (i % 3 == 2) { // 玩家3
                player03.add(poker);
            }
        }

        // 看牌: 打印集合
        System.out.println("玩家1: " + player01);
        System.out.println("玩家2: " + player02);
        System.out.println("玩家3: " + player03);
        System.out.println("底牌3: " + diPai);
    }
}

05、斗地主_抽取

目标: 抽取斗地主的代码

​ 目前代码全部写再main,逻辑上感觉很清晰,实际上,不方便开发和维护的

​ 我们使用面向对象的思维方式,专门搞一个类负责和牌相关的内容

​ 定义一个扑克牌的工具,专门用来操作牌

课堂代码:
// 1.定义牌类
public class Poker {
    private String color;
    private String number;

    public Poker() {
    }

    public Poker(String color, String number) {
        this.color = color;
        this.number = number;
    }

    @Override
    public String toString() {
        return color + number;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}


import java.util.ArrayList;

// 定义一个扑克牌的工具,专门用来操作牌
public class PokerTools {
    // 创建一副牌的方法
    public static ArrayList<Poker> createPoker() {
        //     1.定义牌类
        //     2.创建集合,用于保存一副牌
        ArrayList<Poker> pokers = new ArrayList<>();
        //     3.使用循环生成这副牌
        pokers.add(new Poker("大?", ""));
        pokers.add(new Poker("小?", ""));

        String[] colors = new String[] {"♠", "♥", "♣", "♦"};
        String[] numbers = new String[] {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
        // 一个数字要和所有花色组合
        for (String number : numbers) {
            // 2, A
            for (String color : colors) {
                // "♠", "♥", "♣", "♦"
                Poker poker = new Poker(color, number);
                pokers.add(poker);
            }
        }
        // 返还创建好的牌
        return pokers;
    }

    // 发牌和看牌
    public static void dealPoker(ArrayList<Poker> pokers) {
        //     1.定义3个集合表示3个玩家
        ArrayList<Poker> player01 = new ArrayList<>();
        ArrayList<Poker> player02 = new ArrayList<>();
        ArrayList<Poker> player03 = new ArrayList<>();
        //     2.定义一个集合表示底牌
        ArrayList<Poker> diPai = new ArrayList<>();

        /*
                3.交替发牌
              0   1    2    3    4   5   6    7    8   9   10  ...            51   52  53
            [♦4, ♠Q, ♣10, ♠A, ♥2, ♠3, ♠K, ♠10, ♥J, ♦9, ♦5, ♦2, 大?, ♣8, ♥10, ♦A, ♣]
                    根据索引发牌,规律
            玩家1:    0,3,6       索引 % 3 == 0
            玩家2:    1,4,7       索引 % 3 == 1
            玩家3:    2,5,8       索引 % 3 == 2
         */
        for (int i = 0; i < pokers.size(); i++) {
            // i是索引
            // poker是i索引对应的牌
            Poker poker = pokers.get(i);
            if (i >= 51) {
                diPai.add(poker);
            } else if (i % 3 == 0) { // 玩家1
                player01.add(poker);
            } else if (i % 3 == 1) { // 玩家2
                player02.add(poker);
            } else if (i % 3 == 2) { // 玩家3
                player03.add(poker);
            }
        }

        // 看牌: 打印集合
        System.out.println("玩家1: " + player01);
        System.out.println("玩家2: " + player02);
        System.out.println("玩家3: " + player03);
        System.out.println("底牌3: " + diPai);
    }
}


import java.util.ArrayList;
import java.util.Collections;
public class Demo05 {
    public static void main(String[] args) {
        // 1.创建一副牌
        ArrayList<Poker> pokers = PokerTools.createPoker();

        // 打印集合,看生成的一副牌
        System.out.println(pokers);

        // 2.洗牌
        //         将牌的顺序打乱
        // Collections类:
        // public static void shuffle(List<?> list): 将指定的集合中的元素随机交换位置
        Collections.shuffle(pokers);

        System.out.println("洗牌后: " + pokers);

        // 3.发牌
        PokerTools.dealPoker(pokers);
    }
}

06、数据结构

1、数据结构介绍

​ 数据用什么样的方式组合在一起

2、常见数据结构

​ 栈、队列、数组、链表和红黑树

3、常见数据结构分别来了解一下
1、栈:

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

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

​ 先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹 压进弹夹,
​ 先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下 面的子弹。
​ 栈的入口、出口的都是栈的顶端位置。

这里两个名词需要注意:

​ 压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个 位置。
​ 弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位 置。

2、队列

​ queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而

​ 在表的另一端进行删除

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

​ 先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,小火 车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来。
​ 队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口

[外链图片转存失败(img-98wxMgW4-1563546017464)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563451836131.png)]

3、数组

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

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

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

[外链图片转存失败(img-6y6F3EUZ-1563546017465)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563451951724.png)]

​ 增删元素慢

指定索引位置增加元素:

​ 需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。如下图[外链图片转存失败(img-sE5YLEX0-1563546017467)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563452049854.png)]

指定索引位置删除元素:

​ 需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,
​ 原数组中指定索引位置元素不复制到新数组中。如下图[外链图片转存失败(img-yhTi3h5j-1563546017469)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563452096237.png)]

4、链表

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

​ 简单的说,采用该结构的集合,对元素的存取有如下的特点:
​ 多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左 手,依次类推,这样多个人就连在一起了。
​ 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
​ 增删元素快:[外链图片转存失败(img-vnMATEAF-1563546017470)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563452219552.png)]

5、红黑树

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

​ 简单的理解,就是一种类似于我们生活中树的结构,只不过每个结点上都最多只能有两个子结点。二叉 树是每个节点最多有两个子树的树结构。顶上的叫根结点,两边被称作“左子树”和“右子树”。如图:[外链图片转存失败(img-Gi4MImGn-1563546017472)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563452302266.png)]

​ 我们要说的是二叉树的一种比较有意思的叫做红黑树,红黑树本身就是一颗二叉查找树,将节点插入 后,该树仍然是一颗二叉查找树。如图:[外链图片转存失败(img-JcbgrOEc-1563546017473)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563452349654.png)]

​ 红黑树可以通过红色节点和黑色节点尽可能的保证二叉树的平衡,从而来提高效率。

07、List接口的特点

目标:学习List接口的特点

讲解:

List接口特点:

​ 1.有索引,它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就 是按照11、22、33的顺序完成的)
​ 2.存储和取出有顺序,它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是 一个道理)
​ 3.元素可以重复,集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素

使用List接口中的常用方法:

​ void add(int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)。
​ E get(int index) 返回此列表中指定位置的元素。
​ E remove(int index) 删除该列表中指定位置的元素(可选操作)。
​ E set(int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素。

小结:

​ List接口有哪3个特点?
​ 1.有索引
​ 2.元素可以重复
​ 3.存储和取出有顺序

小贴士:

​ 1.我们在基础班的时候已经学习过List接口的子类java.util.ArrayList类,该类中的方法都是来自List中定义

​ 2.我们之前学习Colletion体系的时候,发现List集合下有很多集合,它们的存储结构不同,这样就导致了这

​ 些集合它们有各自的特点,供我们在不同的环境下使用

课堂代码:
import java.util.ArrayList;
import java.util.List;
public class Demo06 {
    public static void main(String[] args) {
        // 使用List接口的方法
        List<String> list = new ArrayList<>();

        list.add("钱大妈");
        list.add("老干妈");
        list.add("大姨妈");
        list.add("大姨妈");
        list.add("大姨妈");
        list.add("大姨妈");

        // void add (int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)。
        list.add(0, "钱打野");

        System.out.println(list); // [钱打野, 钱大妈, 老干妈, 大姨妈]

        // E get (int index) 返回此列表中指定位置的元素。
        System.out.println(list.get(2));

        // E remove (int index) 删除该列表中指定位置的元素(可选操作)。
        System.out.println(list.remove(1)); // 被删除的元素
        System.out.println("删除后:" + list); // 删除后:[钱打野, 老干妈, 大姨妈]

        // E set (int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素。
        list.set(1, "老干爹");
        System.out.println("修改后: " + list); // 修改后: [钱打野, 老干爹, 大姨妈]
    }
}

08、ArrayList底层

目标:学习ArrayList集合的底层结构

​ 看源码

小结:

​ ArrayList集合的底层结构是什么?
​ 是数组,查询块,增删慢

课堂代码:
import java.util.ArrayList;
public class Demo07 {
    public static void main(String[] args) {
        /*
            public class ArrayList {
                Object[] elementData;

                public ArrayList() {
                    this.elementData = {};
                }

            }

            1.ArrayList内部有一个成员变量Object[] elementData;,ArrayList存储数据就是存到了这个数组中.
            2.在构造方法中,初始化elementData为没有内容的数组
            3.在第一次调用add方法时,数组会初始化为10个长度的数组
            4.调用add方法,当数组的容量不够的时候会进行扩容,新的容量是当前的1.5倍,10 -> 15 -> 22 -> 33
         */

        // 看源码:ctrl + 鼠标左键
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);
        list.add(10);
        list.add(11);
    }
}

09、LinkedList的使用

目标:理解LinkedList集合的底层结构

[外链图片转存失败(img-SdKNItS7-1563546017475)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563449414380.png)]

讲解

​ LinkedList是List的子类,List中的方法LinkedList都是可以使用,这里就不做详细介绍,我们只需要了 LinkedList的特有方法即可。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用

LinkedList的底层:
	是链表
LinkedList特有方法:

​ void addFirst(E e) 在该列表开头插入指定的元素。
​ void addLast(E e) 将指定的元素追加到此列表的末尾。
​ E getFirst() 返回此列表中的第一个元素。
​ E getLast() 返回此列表中的最后一个元素。
​ E removeFirst() 从此列表中删除并返回第一个元素。
​ E removeLast() 从此列表中删除并返回最后一个元素。

小结:

​ 1.LinkedList集合的底层结构是什么?
​ 链表,查询慢,增删块

课堂代码:
import java.util.LinkedList;
public class Demo08 {
	public static void main(String[] args) {
		/*
			class LinkedList {
			    Node<E> first; 第一个节点
				Node<E> last; 最后一个节点
			}

			节点,双向链表
			class Node<E> {
				E item; // 数据域
				Node<E> next; // 下一个节点
				Node<E> prev; // 上一个节点
			}

			LinkedList底层使用的链表.
		 */
		LinkedList<String> linked = new LinkedList<>();
		linked.add("长得帅");
		linked.add("张帅");
		linked.add("郝帅");
		linked.add("都狠帅");

		// void addFirst (E e) 在该列表开头插入指定的元素。
		linked.addFirst("赵德住");
		// void addLast (E e) 将指定的元素追加到此列表的末尾。
		linked.addLast("随便");
		System.out.println(linked); // [赵德住, 长得帅, 张帅, 郝帅, 都狠帅, 随便]

		// E getFirst () 返回此列表中的第一个元素。
		System.out.println(linked.getFirst()); // 赵德住
		// E getLast () 返回此列表中的最后一个元素。
		System.out.println(linked.getLast()); // 随便

		// E removeFirst () 从此列表中删除并返回第一个元素。
		linked.removeFirst();
		// E removeLast () 从此列表中删除并返回最后一个元素。
		linked.removeLast();
		System.out.println(linked);
	}
}

10、Vector基本使用

目标:了解Vector的特点和Enumeration的使用

讲解:
Vector底层使用的是数组,被同步,效率低,所以被淘汰了

​ java.util.Vector集合数和ArrayList一样底层使用数组结构。元素增删慢,查找快,与ArrayList不同的Vector 是线程安全的,速度慢,工作中很少使用。
​ Enumeration elements() 返回此Vector的枚举(迭代器的前身)

小结:

​ 1.Vector的特点?
​ Vector底层使用的是数组,被同步,效率低

​ 2.Enumeration的作用?
​ 相当于迭代器,可以获取集合的元素

​ 3.Enumeration的2个方法?
​ hasMoreElements: 判断是否有下一个元素
​ nextElement(): 获取下一个元素

课堂代码:
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class Demo09 {
    public static void main(String[] args) {
        Vector<String> vec = new Vector<>();
        vec.add("刘德华");
        vec.add("张学友");
        vec.add("黎明");
        vec.add("郭富城");

        // 迭代器
        Iterator<String> itr = vec.iterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }

        // Enumeration:作用和迭代器是一样的,可以获取集合的元素
        //  hasMoreElements: 判断是否有下一个元素
        //  nextElement(): 获取下一个元素
        // elements()得到Enumeration
        Enumeration<String> enu = vec.elements();
        while (enu.hasMoreElements()) {
            System.out.println(enu.nextElement());
        }
    }
}

11、HashSet基本使用

目标:学习Set接口的特点
Set接口特点:
1.没有索引
2.元素不可重复

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

目标:学习HashSet的基本使用

讲解:

Set接口实现类:

​ HashSet

HashSet类说明:

​ 底层是哈希表结构
​ 1.没有索引
​ 2.元素不可重复
​ 3.存储和取出没有顺序

Set接口的方法:

​ boolean add(E e) 添加一个元素
​ boolean remove(Object o) 删除一个元素

注意:

​ 没有修改的方法,也没有获取一个元素的方法,只能通过迭代器来获取数据

小结:

​ 1.说出Set集合特点?
​ 1.没有索引
​ 2.元素不可重复
​ 3.存储和取出没有顺序

​ 2.HashSet如何取出数据?
​ 使用迭代器

课堂代码:
import java.util.HashSet;
import java.util.Iterator;
public class Demo10 {
    public static void main(String[] args) {
        HashSet<String> hs = new HashSet<>();
        hs.add("王昭君");
        hs.add("杨玉环");
        hs.add("貂蝉");
        hs.add("西施");
        hs.add("西施");
        hs.add("西施");
        hs.add("西施");
        // hs.remove("杨玉环");
        // 使用迭代器获取数据
        Iterator<String> itr = hs.iterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }
    }
}

12、LinkedHashSet基本使用

目标:学习LinkedHashSet的使用

​ 我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?

​ 在HashSet下面有一个子类 java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构

小结:

LinkedHashSet的特点?
1.没有索引
2.元素不能重复
3.存储和取出有顺序

import java.util.Iterator;
import java.util.LinkedHashSet;
public class Demo11 {
    public static void main(String[] args) {
        LinkedHashSet<String> lhs = new LinkedHashSet<>();
        lhs.add("cc");
        lhs.add("bb");
        lhs.add("aa");
        lhs.add("dd");

        // 取出来
        Iterator<String> itr = lhs.iterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }

        // 增强for
        for (String el : lhs) {
            System.out.println(el);
        }
    }
}

13、Object类的HashCode方法

目标:能够重写hashCode方法

ctrl + f12看类里面的成员变量和成员方法

讲解:
Object类:
public native int hashCode(); 返回对象的哈希码值。
对象的hashCode相当于人的身份证
默认情况对象的hashCode就是对象的内存地址

​ 我们会重写hashCode,让hashCode值和对象的内容相关
​ hashCode可能会重复,我们要尽量避免hashCode相同

小结
1.Object类中的hashCode方法默认与什么相同?

​ 2.如何重写hashCode方法?
​ 快捷键: alt + insert -> equals() and hashCode()

课堂代码:
import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 重写hashCode
    // @Override
    // public int hashCode() {
    //     return 31 * age + name.hashCode();
    // }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


public class Demo12 {
    public static void main(String[] args) {
        // Person p1 = new Person("凤姐", 18);
        // System.out.println(p1); // 打印对象的地址: 50cbc42f
        // System.out.println(p1.hashCode()); // 打印对象的hashCode: 1355531311
        // System.out.println(Integer.toHexString(p1.hashCode())); // 打印对象的hashCode的十六进制: 50cbc42f

        Person p2 = new Person("a", 18);
        Person p3 = new Person("b", 17);

        System.out.println(p2.hashCode());
        System.out.println(p3.hashCode());

        // String类已经重写了hashCode
        System.out.println("abc".hashCode());
        System.out.println("cba".hashCode());

        System.out.println("通话".hashCode()); // 1179395
        System.out.println("重地".hashCode()); // 1179395
    }
}

14、哈希表的存储元素过程

目标:学习哈希表存储元素的过程

[外链图片转存失败(img-BffUet23-1563546017478)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1563450903830.png)]

讲解:
HashSet底层是哈希表.

小结:

1.说出哈希表存储元素的过程(哈希表判断元素唯一的原理)
1.如果hashCode不相同,直接存储
2.如果hashCode相同,调用equals
2.1 equals返回false,存储
2.2 equals返回true,不存储

注意:

​ 只有底层使用哈希表结构的集合,才需要重写hashCode和equals.确保元素不重复(数据存HashSet/LinkedHashSet才需要重写)

如果元素是存储到ArrayList,LinkedList,不需要重写.

课堂代码:
import java.util.HashSet;
public class Demo13 {
    public static void main(String[] args) {
        HashSet<String> hs = new HashSet<>();

        System.out.println("王健林".hashCode()); // 29089949
        System.out.println("王林".hashCode()); // 943468
        System.out.println("通话".hashCode()); // 1179395
        System.out.println("重地".hashCode()); // 1179395
        System.out.println("王健林".hashCode()); // 29089949


        hs.add("王健林");
        hs.add("王林");
        hs.add("通话");
        hs.add("重地");
        hs.add("王健林");

        System.out.println(hs);
    }
}

15、HashSet存储Student

目标:
创建4个学生存储到HashSet中,学生包含姓名,年龄和分数属性,姓名,年龄和分数相同的人看做同一人,不存储

讲解:
1.定义学生类
2.创建一个HashSet
3.创建4个学生对象
4.将学生对象添加到HashSet集合中

小结:

​ 当我们的元素要存储到HashSet中,HashSet底层使用哈希表,通过元素的HashCode和equals来判断元素是否重复.所以我们自定义的类放到HashSet中时,需要重写hashCode和equals

课堂代码:
// 1.定义学生类
public class Student {
    private String name;
    private int age;
    private double score;

    public Student() {
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        if (Double.compare(student.score, score) != 0) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        temp = Double.doubleToLongBits(score);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}


import java.util.HashSet;
import java.util.Iterator;
public class Demo14 {
    public static void main(String[] args) {
        // 2.创建一个HashSet
        HashSet<Student> stus = new HashSet<>();

        // 3.创建4个学生对象
        Student s1 = new Student("张三", 18, 99);
        Student s2 = new Student("李四", 19, 77);
        Student s3 = new Student("王五", 16, 66);
        Student s4 = new Student("赵六", 66, 66);
        Student s5 = new Student("赵六", 66, 66);

        // s4/s5是两个对象,目前学生类没有重写hashCode,hashCode默认和对象的内存地址一样
        // s4/s5是两个对象,内存地址不一样,意味着hashCode不一样.认为是不同的对象

        // 4.将学生对象添加到HashSet集合中
        stus.add(s1);
        stus.add(s2);
        stus.add(s3);
        stus.add(s4);
        stus.add(s5);

        Iterator<Student> itr = stus.iterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }
    }
}

16、如何选择集合

到目前为止我们学习了常用的集合:
ArrayList,LinkedList,Vector,HashSet,LinkedHashSet

小结:

​ 如何选择集合?
​ 1.如果元素不能重复使用:
​ HashSet,LinkedHashSet

​ 2.如果元素可以重复
​ 2.1 如果查询多使用: ArrayList
​ 2.2 如果增删多使用: LinkedList

​ 不知道就使用ArrayList

17、总结

能够使用迭代器对集合进行取元素

​ 1.获取迭代器
​ 2.循环判断是否有下一个元素
​ 3.取出下一个元素

能够说出List集合特点

​ 1.元素可以重复
​ 2.存储和取出由顺序
​ 3.有索引

能够说出常见的数据结构

​ 栈,队列,数组,链表,红黑树,哈希表

能够说出数组结构特点

​ 查询快,增删慢

能够说出栈结构特点

​ 先进后出

能够说出队列结构特点

​ 先进先出

能够说出单向链表结构特点

​ 查询慢,增删快

能够说出Set集合的特点

​ 1.没有索引
​ 2.元素不可重复

能够说出哈希表的特点

​ 数组和链表组成

使用HashSet集合存储自定义元素
  Student s1 = new Student("张三", 18, 99);
    Student s2 = new Student("李四", 19, 77);
    Student s3 = new Student("王五", 16, 66);
    Student s4 = new Student("赵六", 66, 66);
    Student s5 = new Student("赵六", 66, 66);

    // s4/s5是两个对象,目前学生类没有重写hashCode,hashCode默认和对象的内存地址一样
    // s4/s5是两个对象,内存地址不一样,意味着hashCode不一样.认为是不同的对象

    // 4.将学生对象添加到HashSet集合中
    stus.add(s1);
    stus.add(s2);
    stus.add(s3);
    stus.add(s4);
    stus.add(s5);

    Iterator<Student> itr = stus.iterator();
    while (itr.hasNext()) {
        System.out.println(itr.next());
    }
}

}


# 16、如何选择集合

到目前为止我们学习了常用的集合:
    ArrayList,LinkedList,Vector,HashSet,LinkedHashSet

#### 小结:

​    如何选择集合?
​        1.如果元素不能重复使用:
​            HashSet,LinkedHashSet

​	2.如果元素可以重复
​		2.1 如果查询多使用: ArrayList
​		2.2 如果增删多使用: LinkedList

​	不知道就使用ArrayList



# 17、总结



#### 能够使用迭代器对集合进行取元素

​	1.获取迭代器
​	2.循环判断是否有下一个元素
​	3.取出下一个元素

#### 能够说出List集合特点

​	1.元素可以重复
​	2.存储和取出由顺序
​	3.有索引

#### 能够说出常见的数据结构

​	栈,队列,数组,链表,红黑树,哈希表

#### 能够说出数组结构特点

​	查询快,增删慢

#### 能够说出栈结构特点

​	先进后出

#### 能够说出队列结构特点

​	先进先出

#### 能够说出单向链表结构特点

​	查询慢,增删快

#### 能够说出Set集合的特点

​	1.没有索引
​	2.元素不可重复

#### 能够说出哈希表的特点

​	数组和链表组成

#### 使用HashSet集合存储自定义元素

​	重写元素的hashCode和equals方法
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值