【Collection、List、泛型、数据结构】

**

【Collection、List、泛型、数据结构】

**

第一章 集合

知识点----集合概述

1.1.1集合的概述

集合:集合是java中提供的一种容器,可以用来存储多个引用数据类型的数据。

集合分类:Java中集合分为单列集合与双列集合。

1.1.2集合和数组的区别
  • 长度
    • 数组的长度是固定的
    • 集合的长度是可变的
  • 存储范围
    • 数组可以存储基本类型+引用类型
    • 集合只能存储引用类型
  • 存储内容
    • 数组需指定存储类型
    • 集合默认存储Object类型(任意内容),也可以使用泛型指定要存储的内容类型。
    • 开发中无论是数组还是集合,一般情况建议一个集合\数组存储同一种数据类型。

知识点----单列集合(Collection)概述

1.2.1 单列集合概述

java.util.Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素。

单列集合:以单个对象作为存储元素的集合类型。

1.2.2 单列集合继承体系

java.util.List 有序单列集合接口

  • 特点:元素有索引,元素有序(先进先出)、元素可重复
  • 常用子类
    java.util.ArrayList 	数组结构,查询快,增删慢,线程不安全
    java.util.LinkedList    链表结构,查询慢,增删快,线程不安全
    java.util.Vector    	数组结构,查询较快,增删慢,线程安全
    

java.util.Set 无序单列集合接口

  • 特点:元素无索引,元素无序、元素不可重复
  • 常用子类
    java.util.HashSet		哈希结构,不可排序
      	|-- java.util.LinkedHashSet		链表+哈希表结构,可排序
    java.util.TreeSet		二叉树结构,可排序
    

知识点----单列集合(Collection)常用功能

1.3.1 构造方法

由于Collection是一个接口,不能创建对象,需要使用其子类ArrayLiist类型的创建对象。

1.3.2Collection集合常用功能
public boolean add(E e):  把给定的对象添加到当前集合中 。
public boolean remove(E e): 把给定的对象在当前集合中删除。
public boolean contains(Object obj): 判断当前集合是否包含给定的对象。
public boolean isEmpty(): 判断当前集合是否为空。
public int size(): 返回集合中元素的个数。
public Object[] toArray(): 把集合中的元素,存储到数组中
public void clear():清空集合中所有的元素。

tips: 有关Collection中的方法可不止上面这些,其他方法可以自行查看API学习。

1.3.3演示单列集合常用功能

需求:通过ArrayList类演示单列集合常用功能

//测试类代码

public class Test {
    public static void main(String[] args) {
        //创建集合对象
        Collection<String> c1 = new ArrayList<>();
        //public boolean add(E e)  向集合中添加元素
        c1.add("abc");
        c1.add("def");
        c1.add("hij");
        System.out.println(c1);
        System.out.println("------------------");
        //public boolean remove(E e)  删除集合中元素
        c1.remove("abc");
        System.out.println(c1);
        System.out.println("------------------");
        //public boolean contains(Object obj)  判断是否包含指定的元素
        System.out.println(c1.contains("def"));
        System.out.println(c1.contains("abc"));
        System.out.println("------------------");
        //public boolean isEmpty() 判断是否为空
        System.out.println(c1.isEmpty());
        System.out.println("------------------");
        //public int size() 获取集合的长度
        System.out.println(c1.size());
        System.out.println("------------------");
        //public Object[] toArray()  将集合转换成一个数组
        Object[] array = c1.toArray();
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
        System.out.println("------------------");
        //public void clear() 清空集合中的所有元素
        c1.clear();
        System.out.println(c1.isEmpty());
        System.out.println(c1.size());
    }
}

第二章 Iterator迭代器

2.1.1 Iterator迭代器概述

迭代迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。

每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。

java.util.Iterator Collection集合元素的通用获取方式接口。

2.1.2 获取迭代器对象
public Iterator<E> iterator(): 获取集合对应迭代器,遍历集合中的元素

设计原理:提供统一获取迭代器的方式,由子类实现该方法,获取属于自己的迭代器。

2.1.3 常用方法
public E next()`:返回迭代的下一个元素。
public boolean hasNext():如果仍有元素可以迭代,则返回 true。
2.1.4演示迭代器的使用

需求:通过ArrayList类演示迭代器的使用

//测试类代码

public class Test {
    public static void main(String[] args) {
        //创建集合对象
        Collection<String> c = new ArrayList<>();
        //添加元素
        c.add("abc");
        c.add("def");
        c.add("ghi");
        //获取迭代器对象
        Iterator<String> it = c.iterator();
        //使用迭代器遍历
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}


## 知识点----迭代器的常见异常及实现原理
#### 2.1.1  迭代器常见异常

- java.util.NoSuchElementException		没有集合元素异常  
  - 迭代过程中,当集合中没有元素,继续使用next方法时,抛出此异常。
- ConcurrentModificationException		并发修改异常
  - 迭代过程中,集合元素数量发生变化,继续使用next方法,抛出此异常。

#### 2.1.2  演示迭代器常见异常

需求:通过ArrayList类演示迭代器常见异常

//测试类代码

```java
public class Test {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("abc");
        c.add("def");
        //创建迭代器
        Iterator<String> it = c.iterator();
        //元素不存在异常演示
        /*
        System.out.println(it.next());
        System.out.println(it.next());
        //由于执行next方法的时候,已经没有可以获取的数据,所以提示该位置没有元素的异常
        //System.out.println(it.next());//java.util.NoSuchElementException
        */

        //并发修改异常演示
        while (it.hasNext()) {
            c.add("ghi");
            //next方法执行的时候,会检查迭代器对象中记录的集合长度与当前集合的实际长度是否一致,如果不一致,则报错。
            System.out.println(it.next());//java.util.ConcurrentModificationException
        }
    }
}

2.2.3 迭代器的实现原理

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素

  • 迭代步骤

    • 步骤1:创建迭代器对象,初始化指针,指向0索引位置。
    • 步骤2:hasNext()判断当前指针位置是否有内容。
    • 步骤3:如果有,返回true执行next方法:获取当前位置内容,并将指针后移,回步骤2。
    • 步骤4:如果没有,返回false,表明指针已到末尾,没有可迭代元素,结束迭代。

知识点----增强for循环

2.3.1 概述
  • 增强for循环(foreach循环),是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和Collection集合。
  • 内部基于Iterator迭代器实现,所以在遍历的过程中,不能对集合中的元素进行增删操作,否则抛出ConcurrentModificationException并发修改异常
2.3.2增强for循环格式
for(元素的数据类型  变量 : Collection集合or数组){ 
  	//写操作代码
}
2.3.3演示增强for循环使用

需求:通过ArrayList集合演示增强for循环

//测试类代码

public class Test {
  public static void main(String[] args) {
    //  创建集合对象
    Collection<String> c = new ArrayList();
    //   添加元素
    c.add("abc");
    c.add("def");
    c.add("ghi");
    //  使用for循环遍历打印元素
    for (String s : c) {
      System.out.println(s);
    }
    System.out.println("-------------------");
    int[] arr = {1, 2, 3, 4};
    for (int i : arr) {
      System.out.println(i);
    }
  }
}


第三章 泛型

3.1.1泛型概述

​ JDK5之后,新增了泛型(Generic)语法,可以在类、接口或方法中预支地使用未知的类型。

​ 简单理解:为类、接口或方法提供预定要使用类型限制

​ 泛型使让开发者在设计API时可以指定类或方法支持泛型,使用API的时候也变得更为简洁,并得到了编译时期的语法检查。

3.1.2 泛型在集合中的应用

​ 集合中默认以Object类型存储数据,即多态形式。这种方式,可以存储多种类型数据,但是不便于管理数据,容易造成转换异常java.lang.ClassCastException

​ Collection虽然可以存储各种对象,但实际上通常Collection利用泛型,存储同一类型对象。

3.1.3泛型的好处
  • 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
  • 避免了类型强转的麻烦。
3.1.4 演示泛型在集合中的应用

需求:使用ArrayList集合存储内容,通过遍历,将元素转回字符串类型

//测试类代码

public class Test {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList();
        c.add("abc");
         /*
        //运行时期的问题被转好到了编译时期
        c.add(1);
        c.add('a');
        c.add(true);
        */
        //使用迭代器遍历,获取该集合中的内容
        Iterator it = c.iterator();
        while (it.hasNext()) {
            Object next = it.next();
            String s = (String) next;//java.lang.ClassCastException
            char ch = s.charAt(0);
            System.out.println(ch);
        }

    }
}

tips:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

知识点–泛型的定义及使用

3.3.1含有泛型的类定义和使用格式

​ 泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型,定义对象时,确定泛型类型。

定义格式

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

使用格式

属性类型<泛型类型> 变量名  = new 数据类型<泛型类型>();
属性类型<泛型类型> 变量名  = new 数据类型<>();
3.3.2演示含有泛型的类定义和使用

需求:定义带有泛型的类,并将该泛型应用到参数和返回值类型中。

//泛型类代码

public class GenericsClass<MVP> {
    //使用类上的泛型作为参数
    public void method(MVP mvp) {
        System.out.println(mvp);
    }
    //使用类上的泛型作为返回值
    public MVP method2(MVP mvp) {
        return mvp;
    }
}

//测试类代码

public class Test {
    public static void main(String[] args) {
        //GenericsClass<String> gs = new GenericsClass<String>();
        GenericsClass<String> gs = new GenericsClass<>();
        gs.method("abc");
        String s = gs.method2("aaa");
    }
}
3.3.3含有泛型的方法定义和使用格式

含有泛型的方法参数为泛型类型时才有意义,近似于参数为Object类型的使用,节省了向下转型的过程,在调用方法时,确定泛型类型

定义格式

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

使用格式

对象.方法名(实参)
3.3.4演示含有泛型的方法定义和使用

需求:定义泛型方法,并将该泛型应用到参数和返回值类型中。

//泛型类代码

public class GenericsClass<MVP> {
    //使用类上的泛型作为参数
    public void method(MVP mvp) {
        System.out.println(mvp);
    }
    //使用类上的泛型作为返回值
    public MVP method2(MVP mvp) {
        return mvp;
    }
}

//泛型方法代码

public class Test {
    public static void main(String[] args) {
        GenericsClass gc = new GenericsClass();
        gc.method1("abc");
        String s = gc.method2("aaa");
    }
}
3.3.5含有泛型的接口定义和使用格式

泛型接口约束子类是含有泛型的类型

定义格式

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

使用格式1

修饰符 class 类名 implements  接口名 <数据类型> { }

定义实现类时,确定泛型类型,不写视为Object

使用格式2

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

始终不确定泛型的类型,直到创建对象时,确定泛型的类型

3.3.6演示含有泛型的接口定义和使用

需求:定义泛型接口,将泛型接口应用到方法的返回值类型与参数中

//泛型接口代码

public interface GenericInterface<MVP> {
    public MVP method1();
    public MVP method2(MVP mvp);
}

//泛型接口实现类代码1

public class GenericsClass1 implements GenericInterface<String> {

    @Override
    public String method1() {
        return "GeneircClass1";
    }
    @Override
    public String method2(String s) {
        return s;
    }
}

//泛型接口实现类代码2

public class GenericsClass2<T> implements GenericInterface<T> {

    @Override
    public T method1() {
        if ("GeneircClass2" instanceof String) {
            return (T) "GeneircClass2";
        }
        return null;
    }
    @Override
    public T method2(T t) {
        return t;
    }
}

//测试类代码

public class Test {
    public static void main(String[] args) {
        GenericsClass1 gc1 = new GenericsClass1();
        System.out.println(gc1.method1());
        System.out.println(gc1.method2("hello"));
        System.out.println("--------");
        GenericsClass2<String> gc2 = new GenericsClass2<>();
        System.out.println(gc2.method1());
        System.out.println(gc2.method2("world"));
    }
}

知识点–泛型通配符

3.4.1 概述

泛型通配符:泛型通配符用问号表示(?)

泛型本身不存在继承关系,不可以给已指定泛型的变量接收有其他泛型类型的对象。

//Collection<Object> list = new ArrayList<String>()//错误格式,泛型不存在继承关系

如果想要使变量在未来接收有泛型定义的对象,又不确定泛型要定义的类型。可以使用泛型通配符。

3.4.2 使用格式
数据类型 <?> 对象名称 
对象名 = 带具体泛型类型的对象
3.4.3 受限泛型

限制泛型数据类型的定义区间。

泛型的上限:接收泛型为该泛型数据类型或其子类的对象

格式:数据类型 <? extends 泛型数据类型 > 对象名称

泛型的下限:接收泛型为该泛型数据类型或其父类的对象

格式: 数据类型 <? super 泛型数据类型 > 对象名称
3.4.4演示通配符的基本使用

定义父子孙三个类,在测试类中演示泛型的基本使用及泛型受限的使用

//Fu类代码

public class Fu {

}

//Zi类代码

public class Zi extends Fu {

}

//Sun类代码

public class Sun extends Zi {

}

//测试类代码

public class Test {
    public static void main(String[] args) {
        //泛型不存在继承
        //Collection<Object> list  = new ArrayList<String>();
        //泛型通配符的基本使用
        Collection<?> list = new ArrayList<String>();
        //泛型通配符的高级使用
        //向上受限
        //Collection<? extends Zi> list1 =new ArrayList<Fu>();
        Collection<? extends Zi> list2 = new ArrayList<Zi>();
        Collection<? extends Zi> list3 = new ArrayList<Sun>();
        //向下受限
        Collection<? super Zi> list4 = new ArrayList<Fu>();
        Collection<? super Zi> list5 = new ArrayList<Zi>();
        //Collection<? super Zi> list6 = new ArrayList<Sun>();
    }
}

3.4.5泛型通配符的应用

使用含泛型通配符形式,将拥有泛型的类或接口作为参数

泛型通配符应用方式

形式1:修饰符  返回值 方法名(类名<?> 变量名){}
形式2:修饰符  返回值 方法名(类名<? extends 数据类型>  变量名){}
形式3:修饰符  返回值 方法名(类名<? super 数据类型>  变量名){}
3.4.6演示泛型通配符的应用

需求:使用父子孙类演示泛型受限的使用
//父子孙类代码同上

//测试类代码

public class Sun extends Zi {
    public static void main(String[] args) {
        ArrayList<Fu> list1 = new ArrayList<Fu>();
        ArrayList<Zi> list2 = new ArrayList<Zi>();
        ArrayList<Sun> list3 = new ArrayList<Sun>();
        //泛型通配符应用
        addContent1(list1);
        addContent1(list2);
        addContent1(list3);
        //泛型上限应用
        //addContent2(list1);//由于泛型的上限,所以接收的集合对象的泛型必须是Zi类及其子类
        addContent2(list2);
        addContent2(list3);
        //泛型下限应用
        addContent3(list1);
        addContent3(list2);
        //addContent3(list3);//由于泛型的下限,所以接收的集合对象的泛型必须是Zi类及其父类

    }

    public static void addContent1(Collection<?> list) {

    }

    public static void addContent2(Collection<? extends Zi> list) {

    }

    public static void addContent3(Collection<? super Zi> list) {

    }
}
``

第四章 数据结构

知识点----数据结构概述

4.1数据结构概述
  • 数据结构 : 其实就是存储数据和表示数据的方式
  • 常见的数据结构:堆栈、队列、数组、链表和红黑树

知识点----常见数据结构

4.2.1栈结构

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

名词解释

  • 压栈:就是存元素。

    即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。

  • 弹栈:就是取元素。

    即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。

栈结构特点:

  • 先进后出(即越早存储的元素,越晚取出来)。
  • 栈的入口、出口的都是栈的同一端。

举例:叫号系统

子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹
4.2.2队列结构

概念:队列(queue):,队列结构,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。

队列结构特点

  • 先进先出(即越早存储的元素,越早取出来)。
  • 队列的入口、出口各占一侧。

举例:小火车过山洞

车头先进去,车尾后进去;车头先出来,车尾后出来。
4.2.3数组结构

概念:数组(Array):,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。

数组结构特点:

  • 查找快(通过索引,可以快速访问指定位置的元素)
  • 增删元素慢

举例:出租公寓

有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人
4.2.4链表结构

概念:链表(LinkedList):,由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。

分类:

  • 单向链表:每个单向链表结点包括两个部分:存储数据元素的数据域,存储下一个结点地址的指针域。

  • 双向链表。

链表结构特点

  • 多个结点之间,通过地址进行连接。
  • 查找元素慢:通过连接的节点,依次向后查找指定元素
  • 增删元素快:只需要修改连接下一个元素的地址即可

举例:滑旱冰

每个人使用自己的双手拉住前面的人的衣服。

知识点----树结构介绍

目标:

  • 理解二叉树结构

步骤:

  • 树结构概述
  • 二叉树
  • 二叉查找树
  • 平衡二叉树
  • 平衡二叉树平衡原理
  • 红黑树

讲解:

4.3.1树结构概述

树结构特点

  • 每一个节点有零个或者多个子节点
  • 没有父节点的节点称之为根节点,一个树最多有一个根节点。
  • 每一个非根节点有且只有一个父节点

名词解释

名词含义
节点指树中的一个元素
节点的度节点拥有的子树的个数,二叉树的度不大于2
叶子节点度为0的节点,也称之为终端结点
高度叶子结点的高度为1,叶子结点的父节点高度为2,以此类推,根节点的高度最高
根节点在第一层,以此类推
父节点若一个节点含有子节点,则这个节点称之为其子节点的父节点
子节点子节点是父节点的下一层节点
兄弟节点拥有共同父节点的节点互称为兄弟节点
4.3.2二叉树

概念:如果树中的每个节点的子节点的个数不超过2,那么该树就是一个二叉树。

4.3.3二叉查找树

二叉查找树结构特点:

  • 左子树上所有的节点的值均小于等于他的根节点的值
  • 右子树上所有的节点值均大于或者等于他的根节点的值
4.3.4平衡二叉树

平衡二叉树特点

  • 左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树
  • 避免出现"瘸子"的现象,减少树的高度,提高了搜索效率

4.3.5平衡二叉树平衡原理

平衡二叉树结构中,当有新的节点要插入时,检查是否因插入后而破坏了树的平衡,如果是,则需要做旋转去改变树的结构。

旋转方式:

  • 右旋:左子的右子断连旧父连旧父父,左子升新父。

  • 左旋:右子的左子断连旧父连旧父父,右子升新父。

插入情况分类 :

新节点插入后,需要进行平衡调整,此时将插入元素时的情况分为四种:左左,左右,右左,右右

  • 左左插入调整原理:

    • 左左: 在平衡的二叉树节点左子树的左子树下,插入新节点,导致高度差为2

    • 调整方式:左左调整,只需要对节点进行右旋即可

  • 左右插入调整原理:

  • 左右:在平衡的二叉树节点左子树的右子树下,插入新节点,导致高度差为2

  • 调整方式:将左右进行第一次左旋,调整成左左,然后再对左左进行右旋调整。

  • 右左插入调整原理:

    • 右左:在平衡的二叉树节点右子树的左子树下,插入新节点,导致高度差为2

    • 调整方式:将右左进行第一次右旋,调整成右右,然后再对右右进行左旋调整。

  • 右右插入调整原理:

    • 右右:在平衡的二叉树上节点右子树的右子树下,插入新节点,导致高度差为2

    • 调整方式:左左调整,只需要对节点进行左旋即可

4.3.6红黑树

概念:红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。它是在1972年由Rudolf Bayer发明,当时被称之为平衡二叉B树,1978年Leoj.Guibas和Robert Sedgewick修改为"红黑树"。

红黑树的特性:

  • 根节点是黑色,其他节点是红色或黑色。
  • 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  • 如果一个节点没有儿子,我们称之为叶子节点,红黑树中,叶子被假定为 null 或空,每个叶节点(Nil)是黑色的;
  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

红黑树特点:趋近与平衡树,查询速度快。

红黑树平衡原理:

​ 每一插入,使用红黑数特性规则进行校验,如果不满足红黑规则,就需要左旋和右旋来调整树,使其满足红黑规则;


第五章 List接口

知识点----List接口概述

5.1.1List接口的概述

java.util.List接口继承自Collection接口,是单列集合的一个重要分支。

实现了List接口的类称为List集合。

List接口特点

  • 它是一个元素存取有序的集合
  • 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
  • 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

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


知识点----List接口中常用方法

5.2.1常用方法
  • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index):返回集合中指定位置的元素。
  • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回修改前的元素。
5.2.2演示List接口常用方法

需求:通过ArrayList类演示常用方法

//测试类代码

public class Test {
    public static void main(String[] args) {
        // public void add(int index, E element)
        System.out.println("add------------------");
        List<String> list = new ArrayList<>();
        System.out.println(list);
        list.add("abc");
        list.add("abc");
        System.out.println(list);
        // public E get(int index)
        System.out.println("get------------------");
        List<String> list1 = new ArrayList<>();
        list1.add("abc");
        list1.add("def");
        // System.out.println(list.get(0));
        for (int i = 0; i < list1.size(); i++) {
            System.out.println(list1.get(i));
        }
        // public E remove(int index)`
        System.out.println("remove------------------");
        List<String> list2 = new ArrayList<>();
        list2.add("abc");
        list2.add("def");
        System.out.println(list2);
        list2.remove(0);
        System.out.println(list2);
        // public E set(int index, E element)`
        System.out.println("set------------------");
        List<String> list3 = new ArrayList<>();
        list3.add("abc");
        list3.add("def");
        System.out.println(list3);
        list3.set(0,"ghi");
        System.out.println(list3);
    }
}

`

知识点----List的常用子类

5.3.1ArrayList集合

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

但不建议随意地使用ArrayList完成任何需求,并不严谨,需要根据需求考虑。

ArrayList集合特点:查询快,增删慢,线程不安全

5.3.2LinkedList集合

java.util.LinkedList集合数据存储的结构是双向链表结构。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。

双链表原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W5QSQDbt-1617721961037)(./day05-imgs/常见数据结构原理图/双向链表结构.png)]

LinkedList集合特点:查询慢,增删快,线程不安全

LinkedList集合常用方法(了解即可)

  • public void addFirst(E e):将指定元素插入此列表的开头。
  • public void addLast(E e):将指定元素添加到此列表的结尾。
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素。
  • public E removeFirst():移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。
  • public void push(E e):将元素推入此列表所表示的堆栈。
  • public boolean isEmpty():如果列表不包含元素,则返回true。
5.3.3演示LinkedList集合常用方法

需求:演示LinkedList类常用方法

//测试类代码

public class Test {
  public static void main(String[] args) {
    LinkedList<String> list = new LinkedList();
    list.add("abc");
    list.add("def");
    // public void addFirst(E e)
    list.addFirst("A");
    System.out.println(list);
    // public void addLast(E e)
    list.addLast("Z");
    System.out.println(list);
    // public E getFirst()
    String sta = list.getFirst();
    System.out.println("getFirst:"+sta);
    // public E getLast()
    String end = list.getLast();
    System.out.println("getLast:"+end);
    // public E removeFirst()
    String remf = list.removeFirst();
    System.out.println("removeFirst:"+remf);
    System.out.println(list);
    // public E removeLast()
    String reml = list.removeLast();
    System.out.println("removeLast:"+reml);
    System.out.println(list);
    // public E pop()
    String popStr = list.pop();
    System.out.println(list);
    // public void push(E e)
    list.push("abc");
    System.out.println(list);
    // public boolean isEmpty()
  }
}

``

第六章 模拟斗地主

6.1需求:

按照斗地主的规则,完成洗牌发牌看牌的动作。

具体规则:使用54张牌,三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。

6.2分析:

  • 准备牌:

    • 牌可以设计为一个ArrayList,每个字符串为一张牌。
    • 每张牌由花色数字两部分组成,可以使用花色数组与数字数组嵌套迭代完成每张牌的组合。
    • 将每张牌放进一个牌盒集合
  • 发牌

    • 为每个玩家和剩余底牌各分配一个ArrayList记录牌
    • 将最后3张牌直接存放于底牌中
    • 将剩余牌通过对3取模判断,依次发牌,存入玩家集合中。
  • 看牌

    • 打印玩家集合。
    • 打印底牌集合

6.3实现:

public class Test {
    public static void main(String[] args) {
        /*
        准备牌
        */
        // 设计为一个ArrayList<String>作为牌盒。
        ArrayList<String> pokerBox = new ArrayList<>();
        // 定义一个花色数组
        String[] colors = {"♠", "♥", "♣", "♦"};
        // 定义一个牌号数组
        String[] numbers = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        // 使用循环嵌套,遍历花色和牌号,将每张牌放进一个牌盒集合
        for (int i = 0; i < colors.length; i++) {
            for (int j = 0; j < numbers.length; j++) {
                String card = colors[i] + numbers[j];
                pokerBox.add(card);
            }
        }
        pokerBox.add("小王");
        pokerBox.add("大王");
        //洗牌,调用Collections中的shuffle()方法进行随机洗牌
        Collections.shuffle(cardBox);
     	//发牌
        // 定义3个玩家集合
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        ArrayList<String> dipai = new ArrayList<>();
        for (int i = 0; i < pokerBox.size(); i++) {
            String card = pokerBox.get(i);
            if (i >= pokerBox.size() - 3) {
                dipai.add(card);
            } else {
                if (i % 3 == 0) {
                    player1.add(card);
                } else if (i % 3 == 1) {
                    player2.add(card);
                } else {
                    player3.add(card);
                }
            }
        }
       //看牌
        System.out.println("玩家1:" + player1);
        System.out.println("玩家2:" + player2);
        System.out.println("玩家3:" + player3);
        System.out.println("底牌:" + dipai);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值