一、集合
1.1 概念
集合:集合是java中提供的一种容器,可以用来存储多个数据,并且可以存储任意类型的数据!
容量可以随着存储的数据增大而修改
集合和数组的区别:
- 数组的长度是固定的。集合的长度是可变的。
- 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
1.2 集合体系
1.3 Collection接口
Collection:是所有单列集合类的根接口,用于存储一系列符合某种规则的元素。
集合按存储结构分为:
- 单列集合
java.util.Collection
- 双列集合
java.util.Map
。
两个子接口:
java.util.List
List
的特点是元素有序、元素可重复。
List
接口的主要实现类:
java.util.ArrayList
java.util.LinkedList
java.util.Set
set
集合中的元素不可重复、没有索引
Set
接口的主要实现类有:
java.util.HashSet
java.util.LinkedHashSet
1.4 Collection常用方法
方法名 | 说明 |
---|---|
public boolean add(E e) | 把给定的对象添加到当前集合中 。 |
public boolean remove(E e) | 把给定的对象在当前集合中删除。 |
public boolean contains(E e) | 判断当前集合中是否包含给定的对象。 |
public boolean isEmpty() | 判断当前集合是否为空。 |
public int size() | 返回集合中元素的个数。 |
public Object[] toArray() | 把集合中的元素,存储到数组中。 |
public void clear() | 清空集合中所有的元素。 |
代码演示
//使用多态创建实现类类对象
Collection<String> c=new ArrayList<>();
c.add("张三");//添加方法
c.add("李四");
Object[] array = c.toArray();//将集合转换为数组
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
c.remove("李四");//删除方法
System.out.println(c.contains("张三"));//包含方法
c.clear();//将所有存储数据删除
System.out.println(c);
System.out.println(c.size());//输出存储数据个数
System.out.println(c.isEmpty());//判断是否为空集合
1.5 Iterator迭代器
collection中提供的用于迭代数据的方法,通过该方法可以返回当前集合的迭代器对象,通过迭代器对象提供的方法可以获取迭代集合中的数据
public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。
Iterator
接口的常用方法
方法名 | 说明 |
---|---|
public E next() | 返回迭代的下一个元素。 |
public boolean hasNext() | 如果仍有元素可以迭代,则返回 true。 |
//使用多态创建实现类类对象
Collection<String> c=new ArrayList<>();
c.add("张三");
c.add("李四");
c.add("王五");
//通过iterator方法获取对应集合的迭代器对象
Iterator<String> i=c.iterator();
while(i.hasNext()){//当前集合中是否还有下一个元素
System.out.println(i.next());//获取当前元素
}
- 原理:
通过方法判断是否还存在数据,存在调用方法获取
1.6 增强for循环
增强for循环 (也称
for each
循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
1.6.1 格式
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
1.6.2 原理
在遍历集合时,依次取出集合数据,赋值给中间变量,在循环体中对变量进行操作,再次执行时将数据进行覆盖
//使用多态创建实现类类对象
Collection<String> c=new ArrayList<>();
c.add("张三");
c.add("田七");
c.add("周八");
//通过iterator方法获取对应集合的迭代器对象
Iterator<String> i=c.iterator();
while(i.hasNext()){//当前集合中是否还有下一个元素
System.out.println(i.next());//获取当前元素并指向下一个
}
//for(集合中存储数据的类型 变量名:集合 ){}
for (String s : c) {
System.out.println(s);
}
//先取出张三存储在s中循环使用s,之后取出李四赋值s继续使用
//每次循环 会依次取出数据进行变量的赋值
//变量的值每次循环都会重新赋值
面试题
for
循环与增强for
循环的区别1、语法不同:
for
循环语法中书写初始值、判断条件、迭代语句增强for
循环中书写保存每次取出数据的变量声明以及遍历的数据2、执行流程不同
for
循环按照初始值、判断条件、迭代语句、循环体语句、判断语句 …执行增强for
循环依次取出遍历容器中的数据赋值给临时变量之后使用3、功能不同
for
循环进行容器操作时,使用的是容器提供的方式进行获取并且可以进行修改增强for
循环每次使用临时变量保存,不会修改容器中的数据4、使用场景不同
for
循环可以在执行时根据条件进行终止与操作增强for
循环只能从头到尾遍历所有数据
二、List接口
2.1 概念
java.util.List
接口继承自Collection
接口,是单列集合的一个重要分支,习惯性地会将实现了List
接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
2.2 特点
1、数据有序->存入位置与取出顺序相同
2、拥有索引->可以通过索引精确获取对应数据
3、数据重复->不同索引存储的数据可以相同
2.3 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) | 用指定元素替换集合中指定位置的元素,返回值的更新前的元素。 |
2.4 List接口的实现类
2.4.1 ArrayList
java.util.ArrayList
集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList
是最常用的集合。
2.4.1.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) | 用指定元素替换集合中指定位置的元素,返回值的更新前的元素。 |
public boolean add(E e) | 将指定的元素添加到此列表的尾部 |
2.4.1.2 示例
ArrayList<String> list=new ArrayList<>();
list.add("张三");
//add()方法将指定元素添加至集合末尾
//list集合运允许重复添加相同的数据
list.add("李四");
//add(int,obj)方法将指定元素插入指定索引位置
//原数据依次向后移动
list.add(1,"王五");
//get(int)方法获取指定索引位置数据
System.out.println(list.get(2));
//remove(int)方法 删除指定索引的数据 并返回删除的数据
String remove = list.remove(2);
//set(int,obj)方法 使用新的数据替换指定索引数据
list.set(1, "王二麻子");
//ArrayList重写了toString将数据以[数据1,数据2]字符串的形式返回
System.out.println(list.toString());
2.4.1.3 原理
import java.util.Arrays;
public class MyArrayList {
//ArrayList底层使用数组
//所有数据存储在对应数组中
//设置默认长度10
private String [] values=new String[2];
//实际存储数据个数
private int size=0;
//get(int)方法
public String get(int index){
return values[index];
}
//size()方法
public int size(){
return size;
}
//add(String)方法
public void add(String str){
values[size++]=str;
//添加后进行判断
//如果添加后数组满了创建新的数组进行存储
if(size==values.length){
//将旧数组的数据赋值到新数组
values = Arrays.copyOf(values, 2*size);
}
}
public void add(int index,String str){
System.arraycopy(values, index, values, index+1, size-index);
values[index]=str;
size++;
if(size==values.length){
//将旧数组的数据赋值到新数组
values = Arrays.copyOf(values, 2*size);
}
}
@Override
public String toString() {
StringBuffer sb=new StringBuffer("[");
for (int i = 0; i < size; i++) {
sb.append(values[i]);
if(i!=size-1){
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
2.4.2 LinkedList
java.util.LinkedList
集合数据存储的结构是双向链表结构。方便元素添加、删除的集合,查找修改慢。
2.4.2.1 常用方法
由于其特殊的存储结构。所以额外提供了对起始位置数据的操作方法
方法名 | 说明 |
---|---|
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。 |
2.4.2.2 示例
LinkedList<String> list=new LinkedList<>();
list.add("a");
list.add("b");
list.add("c");
//list.add(0, "new");
//对首位添加
list.addFirst("first");
list.addLast("last");
//在使用上除了对首位末位操作外与ArrayList没有区别
//但是LinkedList存储数据的结构为双向链表
String pop = list.pop();
System.out.println(pop);
System.out.println(list);
2.4.2.3 原理
public class MyLinkedList {
private int size=0;//集合中数据存储数据的个数
private Node first;//首位数据块
private Node last;//末位数据块
public int size(){
return size;
}
public void add(String str){
//使用添加的数据创建一个节点对象
if(size==0){
//如果当前添加的是第一个
Node n=new Node(null, str,null);
//如果是第一个 那么当前保存的首末位应都为当前新创建的对象
first=n;
last=n;
}else {
//将原本的最后一块变为当前块的前一块
Node n=new Node(last,str,null);
//将当前块地址告诉前一块
last.next=n;
//将新添加的块设置为最后一块
last=n;
}
size++;
}
public String get(int index){
if(index>=size){
return null;
}else{
Node n=first;
for (int i = 0; i < index; i++) {
n=n.next;
}
return n.value;
}
}
public Node getFirst() {
return first;
}
public Node getLast() {
return last;
}
//创建内部类 保存每一块的数据
private class Node{
//每一块数据只保存
//上一块的地址
Node prev;
//下一块的地址
Node next;
//当前块保存的数据
String value;
public Node(Node prev, String value, Node next) {
this.value = value;
this.next = next;
this.prev = prev;
}
@Override
public String toString() {
return "Node [value=" + value + "]";
}
}
}
面试题
1、
ArrayList
与LinkedList
的区别
ArrayList
: 底层使用数组形式对数据进行存储
- 查询修改快: 数组可以直接通过索引获取对应位置数据
- 添加删除慢: 在对首位或中间数据进行添加与删除操作时,需要将之后的数据向后或向前移动,随着数据的增大移动的次数也会增大,导致执行的效率降低
LinkedList
: 底层使用双向链表形式对数据进行存储
- 查询修改慢: 底层使用双向链表形式对数据进行存储,每一块只保存当前数据以及前后块地址,在进行查找时,如果查找的是非首末位块,需要依次向后查找
- 添加删除快: 链表每块保存数据添加与删除时只影响前后块位置的修改
2、在实际开发过程中经常使用ArrayList进行数据的存储
- 1、在数据量一定的情况下对ArrayList首位添加删除效率仍然比LinkedList对末位前一位的查找效率高
- 2、在实际开发中添加数据一般都是直接添加至末位,更多的时候是对数据的查找与修改
三、Set接口
3.1 概念
java.util.Set
接口和java.util.List
接口一样,同样继承自Collection
接口,它与Collection
接口中的方法基本一致,并没有对Collection
接口进行功能上的扩充,只是比Collection
接口更加严格了。与List
接口不同的是,Set
接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set
集合有多个子类,这里我们介绍其中的java.util.HashSet
、java.util.LinkedHashSet
这两个集合。
3.2 特点
- Set集合中的元素无序、不可重复
- Set集合没有索引
3.3 Set接口的实现类
3.3.1 HashSet
3.3.1.1 概念
java.util.HashSet
是Set
接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet
底层的实现其实是一个java.util.HashMap
支持,由于我们暂时还未学习,先做了解。
HashSet
是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCode
与equals
方法。
3.3.1.2 HashSet集合的特点
- HashSet集合中的元素不可重复
- HashSet集合没有索引
- HashSet集合是无序的(存储元素的顺序与取出元素顺序可能不一致)
HashSet<Integer> set=new HashSet<>();
set.add(2);
set.add(3);
set.add(5);
set.add(1);
set.add(4);
set.add(4);
System.out.println(set);//[1,2,3,4,5]
3.3.1.3 原理
JDK的版本不同,HashSet集合的数据结构有所不同:
- JDK8之前:数组+链表
- JDK8之后:数组+链表+红黑树(当链表长度超过阈值(8)时,将链表转换为红黑树)
以上数据结构我们称之为是哈希表
3.3.2 LinkedHashSet
3.3.2.1 概念
在HashSet下面有一个子类
java.util.LinkedHashSet
,它是链表和哈希表组合的一个数据存储结构。
3.3.2.2 特点
- LinkedHashSet集合中的元素不可重复
- LinkedHashSet集合没有索引
- LinkedHashSet集合是有序的(存储元素的顺序与取出元素顺序一致)
3.3.2.3 示例
LinkedHashSet<Integer> set=new LinkedHashSet<>();
set.add(5);
set.add(3);
set.add(4);
set.add(1);
set.add(2);
set.add(2);
//LinkedHashSet底层是链表+hash表
//添加数据就是创建新的链表块加入链表
//因为链表每一块只保存关联信息,所以在遍历时必须依次执行
//执行的顺序就是添加的顺序从而导致有序(存入顺序与取出顺序相同)
System.out.println(set);
四、Map接口
4.1 概念
java.util.Map
接口用于存储双列数据结构,现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。
Map集合: 以Key-Value键值对的形式进行数据存储的双列集合
4.2 Map与Collection集合区别
-
Collection集合
单列集合,一次只能添加一个元素 有的是有索引,有的没有索引 有的集合可以存储重复的元素,有的则不可以 有的元素是无序的,有的是有序的
-
Map集合
Map集合是双列集合,由Key和Value组成 Key是不允许重复的,Value是允许重复 Key允许存null值的,但是只能存储唯一的一个 时set集合底层的实现原理
4.3 Map集合中常用的子类
4.3.1 HashMap
存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
4.3.2 LinkedHashMap
4.3.2.1 概念
HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
4.3.2.2 特点
- 有序的,而且key不允许重复
- 数据结构: 哈希表 + 链表
4.4 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>> entrySet() | 获取到Map集合中所有的键值对对象的集合(Set集合)。 |
HashMap<Integer, String> map=new HashMap<>();
map.put(3, "王五");
map.put(1, "张三");
map.put(2, "李四");
map.put(3, "王五1");
//put方法同时添加k-v键值对数据
//在进行添加时首先获取key的hash值进行判断
//是否存在,如果不存在则直接添加
//存在则将value
String put = map.put(4, "赵六");
System.out.println(put);
String put1 = map.put(4, "赵六1");
System.out.println(put1);
//put方法会返回与value类型相同的数据
//如果在添加时,key是新添加的会返回null
//如果添加的key以存在则会将数覆盖,将被覆盖的数据返回
//删除指定Key的键值对 并返回删除的value
String remove = map.remove(4);
System.out.println("remove:"+remove);
//如果删除的key不存在 返回null
String remove1 = map.remove(4);
System.out.println("remove1:"+remove1);
//获取指定key对应的value值
System.out.println("get:"+map.get(2));
//如果不存在对应的key返回null
System.out.println("get1:"+map.get(6));
//是否存在指定key
System.out.println("contains:"+map.containsKey(2));
System.out.println(map);
4.5 map遍历
4.5.1 keySet
- 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示:keyset()
- 遍历键的Set集合,得到每一个键。
- 根据键,获取键所对应的值。方法提示:get(K key)
HashMap<String, String> map=new HashMap<>();
map.put("小鱼儿", "花无缺");
map.put("曹博文", "黄超");
map.put("海绵宝宝", "派大星");
map.put("喜羊羊", "灰太狼");
// 1. 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示:keySet()
Set<String> keySet = map.keySet();
// 2. 遍历键的Set集合,得到每一个键。
for (String string : keySet) {
// 3. 根据键,获取键所对应的值。方法提示:get(K key)
System.out.println(string+"<=>"+map.get(string));
}
4.5.2 entrySet
Map
中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map
中是一一对应关系,这一对对象又称做Map
中的一个Entry(项)
。Entry
将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map
集合时,就可以从每一个键值对(Entry
)对象中获取对应的键与对应的值。
- 获取Entry
Map集合中通过
entrySet()
方法获取Entry对象
public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。
- Entry对象中的常用方法
既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法
方法名 | 说明 |
---|---|
public K getKey() | 获取Entry对象中的键。 |
public V getValue() | 获取Entry对象中的值。 |
- Entry图解
- 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示:entrySet()
- 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
- 通过键值对(Entry)对象,获取Entry对象中的键与值。 方法提示:getkey() getValue()
HashMap<String, String> map=new HashMap<>();
map.put("小鱼儿", "花无缺");
map.put("曹博文", "黄超");
map.put("海绵宝宝", "派大星");
map.put("喜羊羊", "灰太狼");
// 1. 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示:entrySet()
Set<Entry<String,String>> entrySet = map.entrySet();
// 2. 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
for(Entry<String,String> e:entrySet){
// 3. 通过键值对(Entry)对象,获取Entry对象中的键与值。 方法提示:getkey() getValue()
System.out.println(e.getKey()+"<=>"+e.getValue());
}
面试题
1、List集合与Set集合的区别
- List接口,有序可重复
常用实现类ArrayList、LinkedList,额外实现了通过索引操作的方法- Set接口,无序不可重复
常用实现类HashSet,底层使用的map的方法,底层存储数据的结构为数组+链表(jdk8以后达到8之后转换为红黑树),set接口无索引操作,增强了对colleation接口的实现方法2、HashMap与HashTable区别
- hashMap是HashTable的替代
- hashMap线程不安全,HashTable线程安全
- hashMap的key可以使用null作为key
- HashTable的key不允许为null作为key
3、List、Map、Set 三个接口,存取元素时,各有什么特点?
- List:以特定次序来持有元素,可有重复元素。
- Set:无法拥有重复元素,内部排序。
- Map:保存key-value 值,value 可多值,但Key值唯一。
4、Arraylist 与Vector 区别
- 同步性:Vector 是线程安全的(同步),而ArrayList 是线程序不安全的;
- 数据增长:当需要增长时,Vector 默认增长一倍,而ArrayList 却是一半。
4.6 模拟斗地主案例
- 需求
按照斗地主的规则,完成洗牌发牌的动作。
- 具体规则
1. 组装54张扑克牌将
2. 54张牌顺序打乱
3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。
4. 查看三人各自手中的牌(按照牌的大小排序)、底牌
注意: 手中扑克牌从大到小的摆放顺序:大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3
-
需求分析
- 准备牌
完成数字与纸牌的映射关系:
使用双列Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系(相当于一个字典)。
- 洗牌
通过数字完成洗牌发牌
- 发牌
将每个人以及底牌设计为ArrayList,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。
存放的过程中要求数字大小与斗地主规则的大小对应。
将代表不同纸牌的数字分配给不同的玩家与底牌。
- 看牌
通过Map集合找到对应字符展示。
通过查询纸牌与数字的对应关系,由数字转成纸牌字符串再进行展示。
-
代码实现
public class Poker {
public static void main(String[] args) {
/*
* 1组装54张扑克牌
*/
// 1.1 创建Map集合存储
HashMap<Integer, String> pokerMap = new HashMap<Integer, String>();
// 1.2 创建 花色集合 与 数字集合
ArrayList<String> colors = new ArrayList<String>();
ArrayList<String> numbers = new ArrayList<String>();
// 1.3 存储 花色 与数字
Collections.addAll(colors, "♦", "♣", "♥", "♠");
Collections.addAll(numbers, "2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");
// 设置 存储编号变量
int count = 1;
pokerMap.put(count++, "大王");
pokerMap.put(count++, "小王");
// 1.4 创建牌 存储到map集合中
for (String number : numbers) {
for (String color : colors) {
String card = color + number;
pokerMap.put(count++, card);
}
}
/*
* 2 将54张牌顺序打乱
*/
// 取出编号 集合
Set<Integer> numberSet = pokerMap.keySet();
// 因为要将编号打乱顺序 所以 应该先进行转换到 list集合中
ArrayList<Integer> numberList = new ArrayList<Integer>();
numberList.addAll(numberSet);
// 打乱顺序
Collections.shuffle(numberList);
// 3 完成三个玩家交替摸牌,每人17张牌,最后三张留作底牌
// 3.1 发牌的编号
// 创建三个玩家编号集合 和一个 底牌编号集合
ArrayList<Integer> noP1 = new ArrayList<Integer>();
ArrayList<Integer> noP2 = new ArrayList<Integer>();
ArrayList<Integer> noP3 = new ArrayList<Integer>();
ArrayList<Integer> dipaiNo = new ArrayList<Integer>();
// 3.2发牌的编号
for (int i = 0; i < numberList.size(); i++) {
// 获取该编号
Integer no = numberList.get(i);
// 发牌
// 留出底牌,最后三张做为底牌
if (i >= 51) {
dipaiNo.add(no);
} else {
if (i % 3 == 0) {
noP1.add(no);
} else if (i % 3 == 1) {
noP2.add(no);
} else {
noP3.add(no);
}
}
}
// 4 查看三人各自手中的牌(按照牌的大小排序)、底牌
// 4.1 对手中编号进行排序
Collections.sort(noP1);
Collections.sort(noP2);
Collections.sort(noP3);
Collections.sort(dipaiNo);
// 4.2 进行牌面的转换
// 创建三个玩家牌面集合 以及底牌牌面集合
ArrayList<String> player1 = new ArrayList<String>();
ArrayList<String> player2 = new ArrayList<String>();
ArrayList<String> player3 = new ArrayList<String>();
ArrayList<String> dipai = new ArrayList<String>();
// 4.3转换
for (Integer i : noP1) {
// 4.4 根据编号找到 牌面 pokerMap
String card = pokerMap.get(i);
// 添加到对应的 牌面集合中
player1.add(card);
}
for (Integer i : noP2) {
String card = pokerMap.get(i);
player2.add(card);
}
for (Integer i : noP3) {
String card = pokerMap.get(i);
player3.add(card);
}
for (Integer i : dipaiNo) {
String card = pokerMap.get(i);
dipai.add(card);
}
//4.5 查看
System.out.println("令狐冲:"+player1);
System.out.println("石破天:"+player2);
System.out.println("鸠摩智:"+player3);
System.out.println("底牌:"+dipai);
}
}
五、数据结构
5.1 常见的数据结构
数据存储的常用结构有:栈、队列、数组、链表和红黑树。
5.2 栈
栈:stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。
-
栈的特点
- 先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。
- 栈的入口、出口的都是栈的顶端位置。
-
栈的名词
- 压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。
- 弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。
5.3 队列
队列:queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。
- 队列的特点
- 先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,小火车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来。
- 队列的入口、出口各占一侧。。例如,下图中的左侧为入口,右侧为出口。
5.4 数组
数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。
- 数组的特点
- 查找元素快:通过索引,可以快速访问指定位置的元素
- 增删元素慢
- 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。如下图
- 指定索引位置删除元素: 需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。如下图
- 查找元素快:通过索引,可以快速访问指定位置的元素
5.5 链表
链表:linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时i动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。我们常说的链表结构有单向链表与双向链表,那么这里给大家介绍的是单向链表。
- 单向链表数据格式
- 链表的特点
多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
![在这里插入图片描述](https://img-blog.csdnimg.cn/d4bc026bc30b49a88d6df0e30ae8b657.png#pic_center
查找元素慢
:想查找某个元素,需要通过连接的节点,依次向后查找指定元素增删元素快
- 增加元素:只需要修改连接下个元素的地址即可。
- 删除元素:只需要修改连接下个元素的地址即可。
5.6 红黑树
5.6.1 二叉树
binary tree ,是每个结点不超过2的有序树(tree)
简单的理解,就是一种类似于我们生活中树的结构,只不过每个结点上都最多只能有两个子结点。
二叉树是每个节点最多有两个子树的树结构。顶上的叫根结点,两边被称作“左子树”和“右子树”。
5.6.2 红黑树
二叉树的一种比较有意思的叫做红黑树,红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。也就意味着,树的键值仍然是有序的。
-
红黑树的约束
- 节点可以是红色的或者黑色的
- 根节点是黑色的
- 叶子节点(特指空节点)是黑色的
- 每个红色节点的子节点都是黑色的
- 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同
-
红黑树的特点
- 速度特别快,趋近平衡树,查找叶子元素最少和最多次数不多于二倍
每日一点点进步
不进则退