Skip to content

day06 【集合】 ​

今日内容介绍

java
对象数组
Collection接口
迭代器
数据结构
List接口
斗地主案例

第零章 回顾 ​

集合怎么使用 ​

java
//创建集合对象
ArrayList<String> list = new ArrayList<>();
//添加数据到集合中
list.add("迪迦");
list.add("赛文");
// 遍历集合
for(int i = 0;i<list.size();i++){
    String s = list.get(i);
    System.out.println(s);
}

集合的操作套路

java
1:创建容器对象
2: 添加元素到集合对象中
3: 遍历集合

多态 ​

多态是什么?父引用指向子类对象。

**在多态下的一些特点 **

java
public abstract class Animal{

    public abstarct void eat();

}

public class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void play(){
       System.out.println("猫玩毛线");
    }
}

在多态下 写代码
Aniaml a = new Cat();
外表是 Animal
a能调用的功能 是什么?
    只能调用父引用类型中定义的方法!!
    子类特有功能 ,对不起,不能调用。
如果我们要研究一个抽象类或者一个接口中的方法,
可不可以采用多态形式!!!
   可以!!
 研究动物吃
   Aniaml a = new Cat();
  a.eat()
      注意 所有动物都会玩吗?

第一章 Collection 集合【重点】 ​

1.1 集合与数组的区别 ​

java
集合和数组的区别?
1.相同点
    都是引用类型,都是容器,都可以存储对象。
2.区别
   数组是定长的,一旦定义长度不可变。
   集合是不定长的,可以扩容。
   数组可以存储基本类型。

1627529937047

1.2 Collection 集合体系 ​

1627529953354

1.3 Collection 集合中的常用方法 ​

java
java.util.Collection<E>接口:
    常用方法:
        public boolean add(E e) : 把给定的对象添加到当前集合中 。
        public boolean addAll(Collection con):
			把方法参数集合对象con中的所有元素添加到调用方法的集合对象中

        public void clear() :清空集合中所有的元素。
        public boolean remove(E e) : 把给定的对象在当前集合中删除。
            有相同元素,只能删除一个

        public boolean contains(Object obj) : 判断当前集合中是否包含给定的对象。
        public boolean isEmpty() : 判断当前集合是否为空。
        public int size() : 返回集合中元素的个数。
        public Object[] toArray() : 把集合中的元素,存储到数组中。
java
package com.itheima.collection01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class CollectionDemo01 {
    /*
    Collection 单列集合顶层接口,里面定义了所有单列集合应该具备功能
                                     功能都只有声明,需要具体的子类去实现。
                             Collection<E>  ArrayList<E>
                             E 泛型 当前你创建对象的时候 会用具体的类型替换掉E
                     add(E e);  E是泛型 代表你想传什么就是什么

                     boolean isEmpty()如果集合里面没元素就是true 有元素就是false
                    int size(); 查看 集合中有几个元素
                    添加元素到集合  boolean add(E e)  添加成功是true  不成功false
                    boolean contains(Object obj)  判断指定元素是否在集合中
                    boolean remove(Object obj)  删除指定元素 返回删除成功与否
                    清空集合操作 void clear()
     */
    public static void main(String[] args) {
        /*怎么去研究 Collection中的方法?
         * 能直接 new Collection吗? 不行
         *    使用多态形式  父引用 指向子类对象
 6        *      因为 多态下 只能 调用 父接口 里面定义的功能
         */
        // 创建集合对象
        Collection<String> collection = new ArrayList<>();
        // 研究里面定义的方法
       // boolean isEmpty()如果集合里面没元素就是true 有元素就是false
        System.out.println("查看集合是否为空:"+collection.isEmpty());
        // int size(); 查看 集合中有几个元素
        System.out.println("当前集合中有"+collection.size()+"个元素");
        // 添加元素到集合  boolean add(E e)  添加成功是true  不成功false
        System.out.println(collection.add("薇娅"));
        collection.add("张庭");
        System.out.println("当前集合中有"+collection.size()+"个元素");
        // 集合中 有没有 葫芦娃
        // boolean contains(Object obj)  判断指定元素是否在集合中
        System.out.println("当前集合有没有葫芦娃:"+collection.contains("葫芦娃"));
        System.out.println("当前集合有没有薇娅:"+collection.contains("薇娅"));
       // 从集合 删除元素   boolean remove(Object obj)  删除指定元素 返回删除成功与否
        System.out.println("从集合删除葫芦娃:"+collection.remove("葫芦娃"));
        System.out.println("从集合删除薇娅:"+collection.remove("薇娅"));
        System.out.println("当前集合中有"+collection.size()+"个元素");
        // 清空集合操作 void clear()
        collection.clear();
        System.out.println("查看集合是否为空:"+collection.isEmpty());

    }
}

第二章 迭代器 ​

2.0 为什么 Collection 集合形式下 不能进行 fori ​

java
package com.itheima.collection01;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo2 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection<String> collection = new ArrayList<>();
        //添加几个元素
        collection.add("尼古拉斯赵四");
        collection.add("刘能");
        collection.add("谢广坤");
        collection.add("王老七");

        //遍历元素?
//        for(int i = 0;i<collection.size();i++){
//            // 在编译阶段  这里爆了红色问题  为什么?
//          // String s =  collection.get(i);//因为没有该方法 这个方法属于 子类的方法  跟父接口Collection没关系
//            // 不能用  官方说 一些 collection 是有序的,而另一些则是无序的。
//                      // get(index)根据 元素的索引找元素  注意元素如果有索引说明集合是有序的!!
//
//
//        }
        // fori 这种遍历方式  针对Collection整体而言是不行的,只能针对有序的集合。
    }
}

原因:Collection 里面既有有序的又有无序的,而 get 只能操作有序的集合,故而该接口中没有 get 方法。

所以 fori 在 Collection 集合 单列集合这里不是通用的。

既然之前学的 fori 不是通用的 那么对于 Collection 有没有通用的遍历方式,有!!借助外力,使用一个工具叫:迭代器。 帮助我们完成 Collection 集合的遍历。

2.1 迭代器的基本使用 ​

Collection 有个方法 可以获取迭代器

java
Iterator<E> iterator();获取迭代器

迭代器 是一个工具,需要集合对象 叫出来(调用出来),注意每次调用 collection.iterator()都是给你新的迭代器!

这个工具,是用来帮助我们遍历集合。 迭代器中有

next()功能

java
 E next()方法  通过迭代器遍历我们的元素
   注意 这个方法 每次获取完之后指向下一个元素  再获取就是下一个元素

   如果没法获取元素 会出现一个异常  NoSuchElementException
java
package com.itheima.collection01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo3 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection<String> collection = new ArrayList<>();
        //添加几个元素
        collection.add("尼古拉斯赵四");
        collection.add("刘能");
        collection.add("谢广坤");
        collection.add("王老七");
      // 无法fori 只能通过迭代器
        // 迭代器 怎么用能
        // 呼叫出来迭代器
        // 怎么呼叫 调用方法  iterator()方法  每个Collection集合都有独立的 迭代器
        Iterator<String> iterator = collection.iterator();
        // iterator 迭代器 就是来帮我们完成遍历的工具
        // 使用迭代器的 E next()方法 可以获取我们集合中元素
        String next1 = iterator.next();
        System.out.println(next1);
        // 再想获取  再调用一次
        String next2 = iterator.next();
        System.out.println(next2);
        //  next功能有什么特点  获取一个之后  再调用 获取下一个
        String next3 = iterator.next();
        System.out.println(next3);
        String next4 = iterator.next();
        System.out.println(next4);

        String next5 = iterator.next();// 总共四个元素  你调用5次next 爆出了 NoSuchElementException
        System.out.println(next5);
    }
}

2.2 如何再遍历的时候 ,避免 NoSuchElementException 异常 ​

java
iterator.hasNext() 有没有下一个元素  有就进到循环里面 去获取
        如果没有 就结束
        先做判断  有就获取 没有就结束
java
package com.itheima.collection01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo4 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection<String> collection = new ArrayList<>();
        //添加几个元素
        collection.add("尼古拉斯赵四");
        collection.add("刘能");
        collection.add("谢广坤");
        collection.add("王老七");
      // 无法fori 只能通过迭代器
        // 迭代器 怎么用能
        // 呼叫出来迭代器
        // 怎么呼叫 调用方法  iterator()方法  每个Collection集合都有独立的 迭代器
        Iterator<String> iterator = collection.iterator();
        // iterator 迭代器 就是来帮我们完成遍历的工具
        //可不可以将代码进行优化
        // 1:重复代码放到循环中
        // 2:不知道遍历几次 用while循环
        while(iterator.hasNext()){//这里的判断怎么写?
            // 获取 集合中元素  有元素才获取 iterator.hasNext() 有没有下一个元素
            String next = iterator.next();
            System.out.println(next);
        }
    }
}

总结 如何使用迭代器完成的遍历

java
1:通过集合对象得到遍历工具 迭代器   Iterator<String> iterator = collection.iterator();
2:写一个while循环
  while(iterator.hasNext()){ //先判断有没有下一个可以被遍历的元素
     // 有 就获取
    String next=  iterator.next();//这里next只能调用一次
     next就是被遍历出来的元素。
  }

练习: 集合存储自定义类型并遍历 ​

java
//创建标准的学生Student类
public class Student {
    private String name;
    private int age;
    //覆盖重写toString方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
	//空参/满参,set和get
}
java
package com.itheima.collection01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionTest {

    public static void main(String[] args) {
        //创建 Collection对象   存储的自定义类型
        Collection<Student> collection = new ArrayList<>();
       // 存储 三个学生对象到该集合
        Student wyf = new Student("吴亦凡", 32);
        Student hhb = new Student("黄海波", 46);
        Student lzx = new Student("罗志祥", 43);

        collection.add(wyf);
        collection.add(hhb);
        collection.add(lzx);
        // 遍历该集合  输出每个学生对象的名字
        //先获取迭代器
        Iterator<Student> it = collection.iterator();
        // 判断该位置有没有可以获取的元素
        while(it.hasNext()){
            // 如果有   就获取
            Student student = it.next();//获取到当前位置的元素  指针指向下一个了
            System.out.println(student.getName());
        }

    }
}

2.3 迭代器的原理 ​

1641093142371

1641093173824

2.5 并发修改异常--了解即可(面试内容) ​

java
package com.itheima.collection01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo5 {
    public static void main(String[] args) {
        // 创建了一个集合对象  a  b  b  c  d
        Collection<String> arrayList = new ArrayList<>();
        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("b");
        arrayList.add("c");
        arrayList.add("d");
        // 在获取迭代器之前  集合5个元素

        Iterator<String> iterator = arrayList.iterator();
        // 迭代器 感知的集合 里面是  5个元素

        while(iterator.hasNext()){
            String next = iterator.next();
            if(next.equals("b")){
               arrayList.remove("b");// 集合对象删除了b.没有通知迭代器
                                    //集合中元素的个数  4
                                   // 迭代器感知的是  5
                                 // 并发修改  ---迭代器在进行迭代
                                         //  --- 集合修改了长度
            }
        }
        System.out.println(arrayList);
    }
}

1641094654865

观察以上代码,说出运行结果?并解释原因

java
该代码 会爆出一个异常 ConcurrentModificationException
      并发修改异常--就是错误的操作方式。
 arrayList.remove("b");//集合对象   删除元素  是不是就改变了 集合中元素的个数(集合长度)
 在java中 使用迭代器遍历集合元素,那么集合对象不能修改集合的长度。
 如果修改了,就容易出现 并发修改异常。


原因:

1641095014745

使用迭代器遍历的时候,就不能修改集合的元素了吗?

java
可以修改,但是 迭代器与集合要同步好 元素的个数
  集合改完了会不会同步给迭代器,不会。
  但是  迭代器修改了 会同步给集合。
  通过迭代的方法。
java
 if(next.equals("b")){
     // arrayList.remove("b");//集合对象   删除元素  是不是就改变了 集合中元素的个数(集合长度)
     iterator.remove();//删除当前遍历的元素,并同步给集合
 }

结论:

java
使用迭代器遍历元素的时候,就不要进行元素的添加和删除了!!!

第三章 增强 for ​

write less do more 写的少 做的多。

格式:

java
   for(类型 变量名:被遍历的集合或数组){
       // 变量名 是用来接收  被遍历出来的每一个元素的。
   }

作用:简化迭代器的遍历。

底层是迭代器,但是我们不用关注 Iterator 也不用关注 hasNext() next() 只需要关注格式!!

1641095561313

1641095654033

java
package com.itheima.foreach;

import java.util.ArrayList;
import java.util.Collection;

public class ForEachDemo {
    public static void main(String[] args) {
        // 创建了一个集合对象  a  b  b  c  d
        Collection<String> arrayList = new ArrayList<>();
        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("b");
        arrayList.add("c");
        arrayList.add("d");
        /*
        增强for
         */
        for(String s :arrayList){
            System.out.println(s);
        }


    }
}

第四章 List 集合及其子类 ​

1641105036964

4.1 List 集合特点 ​

1641105871293

java
List是有序(存取顺序一致),因为有序,所以有索引。
   实现类主要是保证元素的存取顺序一致,不关心是否有重复元素。
   它特有的功能一定是跟索引相关。
特点
   有序、有索引、可重复

1641106115256

java
Set集合里面的元素是唯一的,不允许出现e1 e2 的equals的值是true,null值只能是一个。
特点
  唯一:集合里面的元素不重复的。
  无序:不保证存取顺序一致。
  没有索引。

4.2 List 集合特有方法 ​

1641105082823

java
package com.itheima.list;

import java.util.ArrayList;
import java.util.List;
/*
       List体系中特有的功能
          add(int index,E e) 往指定索引位置 插入元素
          E get(int index) 根据索引获取元素
          E set(int index,E e)  在指定位置 设置一个新的值 返回一个被替换的值
          E remove(int index) 根据索引删除元素   返回值是被删除的元素
 */
public class ListDemo {
    public static void main(String[] args) {
        //研究List集合
        List<String> list = new ArrayList<>();
        // 添加元素
        list.add("周杰伦");
        list.add("张艺兴");
        list.add("王宝强");
        System.out.println(list);//存取顺序一致
        //  add(int index,E e) 往指定索引位置 插入元素
        list.add(1,"乔杉");
        System.out.println(list);
        // E get(int index) 根据索引获取元素
        String s = list.get(1);
        System.out.println(s);
        // E set(int index,E e)  在指定位置 设置一个新的值 返回一个被替换的值
        String s1 = list.set(1, "胡歌");
        System.out.println("set的返回值:"+s1);

        System.out.println("当前集合的顺序:"+list);
        // E remove(int index) 根据索引删除元素   返回值是被删除的元素
        String remove = list.remove(1);
        System.out.println("被删除的元素:"+remove);

        System.out.println("当前集合中的元素:"+list);
    }
}

4.3 数据结构 ​

概念:数据存储在内存中的方式。

研究什么,看一看有哪些存储方式,它们的特点是什么?

栈 ​

java
栈模型
  出口入口在一端,另一端封闭。
名词
 压栈:元素进入栈模型。
 弹栈:元素离开栈模型。
元素的特点:
   先进后出,后进先出。
应用场景
  子弹夹、java中方法入栈。

1641107559484

队列 ​

java
队列模型
   有两端,入口一端,出口一端
名词
   入队列 从后(入口)端进到队列模型中。
   出队列 从前(出口)端离开队列模型。
元素特点
   先进先出,后进后出
应用
  排队打针,消息队列,秒杀队列

1641107788832

数组 一块连续的空间 ​

java
数组结构
   一段连续的空间结构,每个元素都有索引,而且是挨着的。
特点
  查询快   因为连续且有索引,找每个元素的时间是相同的。
  增删慢   增加或者删除都会改变数组的结构,需要重新构建并且复制元素。

​ 1641108291807

链表 手拉手这种 ​

java
链表结构
   数据是分散存储的,上一个元素都有下一个元素地址值。
特点
  增删快
     只需要进行局部修改就能完成增删。
  查询慢
     查询的时候需要从头找起。

1641108681856

4.4 数组结构集合 ArrayList ​

ArrayList 和 LinkedList 有什么区别?--面试题 ​

java
它们都是List集合,都有索引,它们都能保证存取顺序一致。
ArrayList集合特点:它是数组结构的,查询快,增删慢。它是线程不安全的,所以效率高。
LikedList集合特点:它是链表结构的,查询慢,增删快。它是线程不安全的,所以效率高。
---Vector 集合
    它是数组结构,查询快,增删慢。它是线程安全,效率低。

ArrayList 代码演示略。

4.5 链表结构集合 LinkedList ​

1641110251377

java
package com.itheima.list;

import java.util.LinkedList;

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();

        list.add("乔布斯");
        list.add("古天乐");
        list.add("科比");

        System.out.println("集合中的结构:"+list);//[乔布斯, 古天乐, 科比]

        list.addFirst("c罗");//在链表的头部位置添加元素
        System.out.println("集合中的结构:"+list);
        list.addLast("梅西");
        System.out.println("集合中的结构:"+list);

        System.out.println("获取头部元素:"+list.getFirst());
        System.out.println("集合中的结构:"+list);

        System.out.println("删除头部元素:"+list.removeFirst());
        System.out.println("集合中的结构:"+list);

        System.out.println("弹栈方法:"+list.pop());
        System.out.println("集合中的结构:"+list);

    }
}

第五章 总结及斗地主案例 ​

5.1 Collection 单列集合--List 集合---ArrayList LinkedList ​

java
Collection 单列集合的顶层接口
     里面定义了单列集合都包含的功能
     add(E e)
     remove(E e)
     isEmpty()
     size()
     clear()
     contains()
     toArray() 把集合转换成数组
如何进行单列集合的通用遍历--迭代器
    colliection.iterator()返回一个迭代器对象Iterator<泛型>
    迭代器有什么功能
     hasNext()判断当前位置有没有可以遍历的元素
     next() 获取当前位置元素,并指向下一个
    while(iterator.hasNext()){
        iterator.next();
    }
    比较麻烦
增强for
    for(类型 变量名:被遍历的容器){}
    集合对象.for
    它是 迭代器的简化形式。
    记住 我们在使用迭代遍历的时候,仅仅为遍历,不建议去修改集合。
         因为 如果在用迭代器遍历过程中,修改了 集合中长度,那么会出现兵法修改异常。
List集合
   特点 元素存取顺序一致 可以存储重复元素 有索引
   它的特有功能跟索引相关
       add(int index,E e)指定位置添加元素
       set(int index,E e)指定位置修改指定元素
       get(int index)获取指定位置元素
       remove(int index)删除指定位置元素
四种数据结构
    栈 先进后出
    队列 先进先出
    数组  查询快 增删慢
    链表  查询慢 增删快
List的子类
    ArrayList LinkedList 区别参考上面内容

List集合有几种遍历方式?
   普通的迭代器
   增强for
   fori的形式(索引形式)

  如果仅仅是查看元素  用增强for。
  如果你还想修改元素  使用fori。

5.2 斗地主案例 ​

分析:

1641114754781

代码:

java
package com.itheima.poker;

import java.util.ArrayList;
import java.util.Collections;

public class Poker {
    public static void main(String[] args) {
        /*
        1:准备牌
         1.1 创建一个ArrayList集合 pokerList
         1.2 创造54张牌
            花色 ♠  ♣  ♥ ♦
            数字 2-10 J Q K A
            大♛  小♚
            1.2.1 先把 大王小王存到集合中
            1.2.2 构建另外52张牌
               花色+数字组成
               每一个花色 和 每一个数字 拼接
               准备花色集合 ♠  ♣  ♥ ♦
               准备数字集合 2-10 J Q K A
           1.2.3
              先遍历花色 得到每个花色
                再遍历数字 每个花色+数字 拼接 形成了牌面
           1.2.4     把 牌面存储到扑克集合中
         */
        //1:准备牌
        // 1.1 创建 牌盒
        ArrayList<String> pokerList = new ArrayList<>();
        //1.2 创造牌
        //1.2.1  完成大小王的存储
        pokerList.add("大♛");
        pokerList.add("小♚");
        // 1.2.  构建另外52张牌
        // 1.2.2 创建两个集合
        // 花色集合
        ArrayList<String> colors = new ArrayList<>();
        //数字集合
        ArrayList<String> numbers = new ArrayList<>();
        //存花色
        colors.add("♠");
        colors.add("♣");
        colors.add("♥");
        colors.add("♦");

        // 2~10
        for (int i = 2; i <=10 ; i++) {
            numbers.add(i+"");//基本类型变为字符串
        }
        //存数字
        numbers.add("J");
        numbers.add("Q");
        numbers.add("K");
        numbers.add("A");
        // 1.2.3 遍历 花色和数字
        for (String color : colors) {
            //color就是一种花色
            for (String number : numbers) {
                //number就是数字
                //1.2.4 拼接牌面
                String card = color+number;
                //牌面存储到 牌盒中
                pokerList.add(card);
            }
        }

        System.out.println("洗牌之前"+pokerList);
      /*
      2:洗牌
        就是打乱集合中元素的顺序
           工具类 Collections.shuffle(list集合)
       */
        Collections.shuffle(pokerList);
        System.out.println("洗牌后:"+pokerList);

        /*
        3:发牌
           3.1 创建四个集合 三个玩家 一个底牌集合
           3.2 发牌 采用fori 因为需要索引进行判断发牌
               采用 fori的形式 遍历牌盒
               怎么去发  ?
               根据索引发牌面
                 先获取 当前索引对应的牌面
                 再决定这张牌 发给谁。
                   通过 i索引的判断
                       留底牌  i>=51
                          对 3 取余
                             0  发给 UZI
                             1  发给 LBW
                             2  发给 PDD
         */
//        3.1 创建四个集合 三个玩家 一个底牌集合
        ArrayList<String> uzi = new ArrayList<>();
        ArrayList<String> lbw = new ArrayList<>();
        ArrayList<String> pdd = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();

        // 3.2 遍历牌盒
        for (int i = 0; i < pokerList.size(); i++) {
            //先获取牌面
            String card = pokerList.get(i);
            //再发牌
            //先留出底牌
            if(i>=51){
                //牌面给底牌集合
                dipai.add(card);
            }else if(i%3==0){//索引3取余 0 给uzi
                //玩家一
                uzi.add(card);
            }else if(i%3==1){//索引3取余 0 给lbw
                //玩家er
                lbw.add(card);
            }else{
                pdd.add(card);
            }
        }

        // 4:查看牌
        System.out.println("简自豪:"+uzi);
        System.out.println("卢本伟:"+lbw);
        System.out.println("刘谋:"+pdd);
        System.out.println("底牌:"+dipai);
    }
}

Released under the MIT License.