java基础——迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类

news/2024/11/22 22:55:57/

迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类

第一章 Iterator迭代器

1.1 Iterator接口

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator

想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作
,下面介绍一下获取迭代器的方法:

  • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。

下面介绍一下迭代的概念:

  • 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator接口的常用方法如下:

  • public E next():返回迭代的下一个元素。
  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

接下来我们通过案例学习如何使用Iterator迭代集合中元素:

public class IteratorDemo {public static void main(String[] args) {// 使用多态方式 创建对象Collection<String> coll = new ArrayList<String>();// 添加元素到集合coll.add("串串星人");coll.add("吐槽星人");coll.add("汪星人");//遍历//使用迭代器 遍历   每个集合对象都有自己的迭代器Iterator<String> it = coll.iterator();//  泛型指的是 迭代出 元素的数据类型while(it.hasNext()){ //判断是否有迭代元素String s = it.next();//获取迭代出的元素System.out.println(s);}}
}

tips:

  1. 在进行集合元素获取时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会抛出java.util.NoSuchElementException没有集合元素异常。
  2. 在进行集合元素获取时,如果添加或移除集合中的元素 , 将无法继续迭代 , 将会抛出ConcurrentModificationException并发修改异常.

1.2 迭代器的实现原理

我们在之前案例已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例来演示Iterator对象迭代元素的过程:

请添加图片描述

在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

第二章 数据结构

2.1 数据结构介绍

数据结构 : 数据用什么样的方式组合在一起。

2.2 常见数据结构

数据存储的常用结构有:栈、队列、数组、链表和红黑树。我们分别来了解一下:

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

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

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

这里两个名词需要注意:

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

队列

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

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

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

数组

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

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

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

  • 增删元素慢

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

  • **指定索引位置删除元素:**需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。

链表

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

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

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

  • 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素

  • 增删元素快:

2.3. 树基本结构介绍

树具有的特点:

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

二叉树

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

二叉查找树/二叉排序树

二叉查找树的特点:

  1. 左子树上所有的节点的值均小于等于他的根节点的值
  2. 右子树上所有的节点值均大于或者等于他的根节点的值
  3. 每一个子节点最多有两个子树

增删改查的性能都很高!!!

遍历获取元素的时候可以按照"左中右"的顺序进行遍历;

注意:二叉查找树存在的问题:会出现"瘸子"的现象,影响查询效率。

平衡二叉树

(基于查找二叉树,但是让树不要太高,尽量让树的元素均衡分布。这样综合性能就高了)

概述

为了避免出现"瘸子"的现象,减少树的高度,提高我们的搜素效率,又存在一种树的结构:“平衡二叉树”

规则:它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树

旋转

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

左旋:

左旋就是将节点的右支往左拉,右子节点变成父节点,并把晋升之后多余的左子节点出让给降级节点的右子节点;

右旋:

将节点的左支往右拉,左子节点变成了父节点,并把晋升之后多余的右子节点出让给降级节点的左子节点

由于在构建平衡二叉树的时候,当有新节点插入时,都会判断插入后时候平衡,这说明了插入新节点前,都是平衡的,也即高度差绝对值不会超过1。当新节点插入后,

有可能会有导致树不平衡,这时候就需要进行调整,而可能出现的情况就有4种,分别称作左左,左右,右左,右右

红黑树

就是平衡的二叉查找树!!

概述

红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构,它是在1972年由Rudolf Bayer发明的,当时被称之为平衡二叉B树,后来,在1978年被

Leoj.Guibas和Robert Sedgewick修改为如今的"红黑树"。它是一种特殊的二叉查找树,红黑树的每一个节点上都有存储位表示节点的颜色,可以是红或者黑;

红黑树不是高度平衡的,它的平衡是通过"红黑树的特性"进行实现的;

红黑树的特性:

  1. 每一个节点或是红色的,或者是黑色的。
  2. 根节点必须是黑色
  3. 每个叶节点(Nil)是黑色的;(如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点)
  4. 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
  5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点;

如下图所示就是一个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWCyvTPy-1681788575306)(img/1562653205543.png)]

在进行元素插入的时候,和之前一样; 每一次插入完毕以后,使用黑色规则进行校验,如果不满足红黑规则,就需要通过变色,左旋和右旋来调整树,使其满足红黑规则;

第三章 List接口

我们掌握了Collection接口的使用后,再来看看Collection接口中的子类,他们都具备那些特性呢?

接下来,我们一起学习Collection中的常用几个子类(java.util.List集合、java.util.Set集合)。

3.1 List接口介绍

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

看完API,我们总结一下:

List接口特点:

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

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

3.2 List接口中常用方法

List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:

  • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index):返回集合中指定位置的元素。
  • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

List集合特有的方法都是跟索引相关,我们在基础班都学习过。

tips:我们之前学习Colletion体系的时候,发现List集合下有很多集合,它们的存储结构不同,这样就导致了这些集合它们有各自的特点,供我们在不同的环境下使用,那么常见的数据结构有哪些呢?在下一章我们来介绍:

3.3 ArrayList集合

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

许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。

3.4 LinkedList集合

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

LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uAsxiPoM-1681788575307)(img/%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8.png)]

实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而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。

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

public class Demo04LinkedList {public static void main(String[] args) {method4();}/**  void push(E e): 压入。把元素添加到集合的第一个位置。*  E pop(): 弹出。把第一个元素删除,然后返回这个元素。*/public static void method4() {//创建LinkedList对象LinkedList<String> list = new LinkedList<>();//添加元素list.add("达尔文");list.add("达芬奇");list.add("达尔优");System.out.println("list:" + list);//调用push在集合的第一个位置添加元素//list.push("爱迪生");//System.out.println("list:" + list);//[爱迪生, 达尔文, 达芬奇, 达尔优]//E pop(): 弹出。把第一个元素删除,然后返回这个元素。String value = list.pop();System.out.println("value:" + value);//达尔文System.out.println("list:" + list);//[达芬奇,达尔优]}/** E removeFirst():删除第一个元素* E removeLast():删除最后一个元素。*/public static void method3() {//创建LinkedList对象LinkedList<String> list = new LinkedList<>();//添加元素list.add("达尔文");list.add("达芬奇");list.add("达尔优");//删除集合的第一个元素
//		String value = list.removeFirst();
//		System.out.println("value:" + value);//达尔文
//		System.out.println("list:" + list);//[达芬奇,达尔优]//删除最后一个元素String value = list.removeLast();System.out.println("value:" + value);//达尔优System.out.println("list:" + list);//[达尔文, 达芬奇]}/** E getFirst(): 获取集合中的第一个元素* E getLast(): 获取集合中的最后一个元素*/public static void method2() {//创建LinkedList对象LinkedList<String> list = new LinkedList<>();//添加元素list.add("达尔文");list.add("达芬奇");list.add("达尔优");System.out.println("list:" + list);//获取集合中的第一个元素System.out.println("第一个元素是:" + list.getFirst());//获取集合中的最后一个元素怒System.out.println("最后一个元素是:" + list.getLast());} /** void addFirst(E e): 在集合的开头位置添加元素。* void addLast(E e): 在集合的尾部添加元素。*/public static void method1() {//创建LinkedList对象LinkedList<String> list = new LinkedList<>();//添加元素list.add("达尔文");list.add("达芬奇");list.add("达尔优");//打印这个集合System.out.println("list:" + list);//[达尔文, 达芬奇, 达尔优]//调用addFirst添加元素list.addFirst("曹操");System.out.println("list:" + list);//[曹操, 达尔文, 达芬奇, 达尔优]//调用addLast方法添加元素list.addLast("大乔");System.out.println("list:" + list);//[曹操, 达尔文, 达芬奇, 达尔优, 大乔]}
}

第四章 Set接口

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

Set集合有多个子类,这里我们介绍其中的java.util.HashSetjava.util.LinkedHashSetjava.util.TreeSet这两个集合。

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

4.1 HashSet集合介绍

java.util.HashSetSet接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不能保证不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持,由于我们暂时还未学习,先做了解。

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

我们先来使用一下Set集合存储,看下现象,再进行原理的讲解:

public class HashSetDemo {public static void main(String[] args) {//创建 Set集合HashSet<String>  set = new HashSet<String>();//添加元素set.add(new String("cba"));set.add("abc");set.add("bac"); set.add("cba");  //遍历for (String name : set) {System.out.println(name);}}
}

输出结果如下,说明集合中不能存储重复元素:

cba
abc
bac

tips:根据结果我们发现字符串"cba"只存储了一个,也就是说重复的元素set集合不存储。

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

什么是哈希表呢?

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

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

看到这张图就有人要问了,这个是怎么存储的呢?

为了方便大家的理解我们结合一个存储流程图来说明一下:

在这里插入图片描述

总而言之,JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

4.3 HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一.

创建自定义Student类:

public class Student {private String name;private int age;//get/set@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}

创建测试类:

public class HashSetDemo2 {public static void main(String[] args) {//创建集合对象   该集合中存储 Student类型对象HashSet<Student> stuSet = new HashSet<Student>();//存储 Student stu = new Student("于谦", 43);stuSet.add(stu);stuSet.add(new Student("郭德纲", 44));stuSet.add(new Student("于谦", 43));stuSet.add(new Student("郭麒麟", 23));stuSet.add(stu);for (Student stu2 : stuSet) {System.out.println(stu2);}}
}
执行结果:
Student [name=郭德纲, age=44]
Student [name=于谦, age=43]
Student [name=郭麒麟, age=23]

4.4 LinkedHashSet

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

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

演示代码如下:

public class LinkedHashSetDemo {public static void main(String[] args) {Set<String> set = new LinkedHashSet<String>();set.add("bbb");set.add("aaa");set.add("abc");set.add("bbc");Iterator<String> it = set.iterator();while (it.hasNext()) {System.out.println(it.next());}}
}
结果:bbbaaaabcbbc

4.5 TreeSet集合

1. 特点

TreeSet集合是Set接口的一个实现类,底层依赖于TreeMap,是一种基于红黑树的实现,其特点为:

  1. 元素唯一
  2. 元素没有索引
  3. 使用元素的自然顺序对元素进行排序,或者根据创建 TreeSet 时提供的 Comparator 比较器
    进行排序,具体取决于使用的构造方法:
public TreeSet():								根据其元素的自然排序进行排序
public TreeSet(Comparator<E> comparator):    根据指定的比较器进行排序

2. 演示

案例演示自然排序(20,18,23,22,17,24,19):

public static void main(String[] args) {//无参构造,默认使用元素的自然顺序进行排序TreeSet<Integer> set = new TreeSet<Integer>();set.add(20);set.add(18);set.add(23);set.add(22);set.add(17);set.add(24);set.add(19);System.out.println(set);
}控制台的输出结果为:
[17, 18, 19, 20, 22, 23, 24]

案例演示比较器排序(20,18,23,22,17,24,19):

public static void main(String[] args) {//有参构造,传入比较器,使用比较器对元素进行排序TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {//元素前 - 元素后 : 升序//元素后 - 元素前 : 降序return o2 - o1;}});set.add(20);set.add(18);set.add(23);set.add(22);set.add(17);set.add(24);set.add(19);System.out.println(set);
}控制台的输出结果为:
[24, 23, 22, 20, 19, 18, 17]

第五章 Collections类

5.1 Collections常用功能

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

    常用方法如下:

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

  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。

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

代码演示:

public class CollectionsDemo {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();list.add(100);list.add(300);list.add(200);list.add(50);//排序方法 Collections.sort(list);System.out.println(list);}
}
结果:
[50,100, 200, 300]

我们的集合按照默认的自然顺序进行了排列,如果想要指定顺序那该怎么办呢?

5.2 Comparator比较器

创建一个学生类,存储到ArrayList集合中完成指定排序操作。

Student 类

public class Student{private String name;private int age;//构造方法//get/set//toString
}

测试类:

public class Demo {public static void main(String[] args) {// 创建四个学生对象 存储到集合中ArrayList<Student> list = new ArrayList<Student>();list.add(new Student("rose",18));list.add(new Student("jack",16));list.add(new Student("abc",20));Collections.sort(list, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge()-o2.getAge();//以学生的年龄升序}});for (Student student : list) {System.out.println(student);}}
}
Student{name='jack', age=16}
Student{name='rose', age=18}
Student{name='abc', age=20}

5.3 可变参数

JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化.

格式:

修饰符 返回值类型 方法名(参数类型... 形参名){  }

代码演示:

  public class ChangeArgs {public static void main(String[] args) {int sum = getSum(6, 7, 2, 12, 2121);System.out.println(sum);}public static int getSum(int... arr) {int sum = 0;for (int a : arr) {sum += a;}return sum;}
}

注意:

​ 1.一个方法只能有一个可变参数

​ 2.如果方法中有多个参数,可变参数要放到最后。

应用场景: Collections

​ 在Collections中也提供了添加一些元素方法:

public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。

代码演示:

public class CollectionsDemo {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();//原来写法//list.add(12);//list.add(14);//list.add(15);//list.add(1000);//采用工具类 完成 往集合中添加元素  Collections.addAll(list, 5, 222, 12);System.out.println(list);
}

第六章 集合综合案例

6.1 案例介绍

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

使用54张牌打乱顺序,三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。

6.2 案例分析

  • 准备牌:

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

  • 发牌

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

  • 看牌

    直接打印每个集合。

6.3 代码实现

  1. Poker.java
public class Poker {private String name;public Poker() {}public Poker(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "{" + name + "}";}
}

2 测试类

public class Demo12 {public static void main(String[] args) {// 创建一个ArrayList用于存放一副牌ArrayList<Poker> pokers = new ArrayList<>();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"};// 组合牌, 嵌套循环的流程:外循环一次,内循环所有次// 2.使用嵌套循环生成一副牌for (String n : numbers) {// "2", "A"for (String c : colors) {// "♠", "♥", "♣", "♦"Poker p = new Poker(c, n);// 3.将54张牌放到集合pokers.add(p);}}// 打印
//        System.out.println(pokers);// 洗牌: Collections,集合工具类// static void shuffle​(List<?> list) 将集合中元素的顺序打乱Collections.shuffle(pokers);System.out.println("洗牌后:" + pokers);// 发牌// 1.创建3个玩家集合,创建底牌集合ArrayList<Poker> player01 = new ArrayList<>();ArrayList<Poker> player02 = new ArrayList<>();ArrayList<Poker> player03 = new ArrayList<>();ArrayList<Poker> diPai = new ArrayList<>();// 2.遍历牌的集合//            0     1      2     3     4     5      6     7     8      9     10 ...51    52     53// pokers = [♦5], [♣4], [♦8], [♣A], [♣7], [♦2], [♠6], [♣J], [♥A], [♥7], [♥6], [♣5], [♦7], [♥10]// 玩家1:   索引0,3,6       索引 % 3 == 0// 玩家2:   索引1,4,7       索引 % 3 == 1// 玩家3:   索引2,5,8       索引 % 3 == 2// 3.根据索引将牌发给不同的玩家for (int i = 0; i < pokers.size(); i++) {// i表示索引,poker就是i索引对应的pokerPoker poker = pokers.get(i);if (i >= 51) { // 最后3张给底牌diPai.add(poker);} else if (i % 3 == 0) { // 玩家1player01.add(poker);} else if (i % 3 == 1) { // 玩家2player02.add(poker);} else if (i % 3 == 2) { // 玩家3player03.add(poker);}}// 看牌System.out.println("玩家1: " + player01);System.out.println("玩家2: " + player02);System.out.println("玩家3: " + player03);System.out.println("底牌: " + diPai);// 还要创建一副牌// 创建一个ArrayList用于存放一副牌}
}

http://www.ppmy.cn/news/47312.html

相关文章

【unity实战】随机地下城生成2——绘制地图Tilemap的使用及一些技巧的使用(含源码)

绘制房间 修改素材配置 切割图片 绘制瓦片地图 先新建我们的调色盘,保存好位置 拖入我们刚才切片好的素材 在房间预设体创建我们的瓦片地图 绘制地图的小技巧 点选移动适合的瓦片移动到位置上绘画 框选复制已经绘制好的地图,快捷键i

rust的并发以及kv server网络处理和网络安全部分

理解并发和并行 Golang 的创始人之一&#xff0c;对此有很精辟很直观的解释&#xff1a;并发是一种同时处理很多事情的能力&#xff0c;并行是一种同时执行很多事情的手段。 我们把要做的事情放在多个线程中&#xff0c;或者多个异步任务中处理&#xff0c;这是并发的能力。在多…

APP渗透—MobSF安全评估、frida、r0capture抓包

APP渗透—MobSF安全评估、frida、r0capture抓包 1. 前言2. 补充AppInfoScanner相关内容3. MobSF安全评估3.1. 下载MobSF3.2. 安装Docker3.2.1. 查看Linux内核版本3.2.2. 更新yum包3.2.3. 安装Docker软件包3.2.4. 设置yum源3.2.5. 查看Docker版本3.2.6. 安装Docker3.2.7. 设置Do…

[Python基础] 序列(列表/元组)和字典的操作详解

文章目录 序列概念序列列表列表的创建和下标访问创建下标 列表的切片操作列表的遍历列表的插入操作列表的查找和删除列表的拼接 元组元组的相关操作 字典概念字典的创建查找字典中的key&#xff0c;value字典的增删改字典的遍历 序列概念 包含若干个元素, 元素有序排列, 可以通…

Chapter10-NameServer 源码解析

10.1 模块人口代码的功能 10.1.1 入口函数 首先看一下 NameServer 的源码目录&#xff08;见图 10-1 &#xff09; 。NamesrvStartup 是模块的启动入 口&#xff0c; NamesrvController 是用来协块各个调模功能的代码。 我们从启动代码开始分析&#xff0c;找到 NamesrvStartup…

JavaScript【一】JavaScript变量与数据类型

文章目录 &#x1f31f;前言&#x1f31f;变量&#x1f31f; 变量是什么&#xff1f;&#x1f31f; 变量提升&#x1f31f; 声明变量&#x1f31f; JavaScript有三种声明方式&#x1f31f; 命名规范&#x1f31f; 注意 &#x1f31f;数据类型以及运算&#x1f31f; 检测变量数据…

MySQL运维28-MySQL复制

文章目录 1、MySQL复制模式2、MySQL复制的兼容性3、与MySQL复制相关的两种日志3.1、中继日志3.2、MySQL复制的状态日志 4、MySQL主从复制的实施示例4.1、主从库安装4.2、主库配置4.3、从库的配置4.4、启动复制和确认成功 5、对MySQL复制的监控6、MySQL监控的运维6.1、在从库修改…

第二部分——长难句——第一章——并列句

conjunction(and,but,if,when(while)) 想把两个句子&#xff08;多件事&#xff09;连在一块&#xff0c;就必须加上连词。 所以长难句到底是啥&#xff1f; 所以长难句&#xff08;直白表达&#xff0c;并不是语法表述&#xff09;就是几个简单句多家上几个连接词就齐活了&am…