一、集合框架
1.1 概述
集合:集合是Java中提供的一种容器,可以用来存储多个数据。
集合和数组:
- 数组的长度是固定的。集合的长度是可变的。
int[] arr = new int[10];
- 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一样,在开发中一般当对象多的时候,使用集合进行存储。
1.2 集合框架
学习顶层:学习顶层接口/抽象类中共性的方法,所有的子类都可以使用。
使用底层:上层不是接口就是抽象类,无法创建对象使用,需要使用底层的子类创建对象使用

二、Collection接口
java.util.Collection
- boolean add(E e) 确保此集合包含指定的元素(可选操作)。
- void clear() 从此集合中删除所有元素(可选操作)。
- boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。
- boolean isEmpty() 如果此集合不包含元素,则返回 true 。
- boolean remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
- int size() 返回此集合中的元素数。
- Object[] toArray() 返回一个包含此集合中所有元素的数组。
三、Iterator迭代器接口
java.util.Iterator 接口:迭代器(对集合进行遍历)。
3.1 常用方法
boolean hasNext() //如果仍有元素可以迭代,则返回true。判断集合中还有没有下一个元素,有就返回true,没有则返回falseE next() //返回迭代的下一个元素
Collection接口中有一个方法iterator(),这个方法返回的就是迭代器的实现类对象
Iterator<E> iterator() 返回在次Collection的元素上进行迭代的迭代器
使用步骤:
① 使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)。
② 使用Iterator接口中的方法hasNext判断还有没有下一个元素。
③ 使用Iterator接口中的方法next取出集合中的下一个元素
注意:Iterator接口是有泛型的迭代器的泛型跟着集合走。集合什么泛型,他就什么泛型
实现原理:

3.2 增强for循环
底层使用的也是迭代器,只是使用for循环的格式,简化了迭代器的书写(JDK1.5以后的新特性)。
for(集合/数组的数据类型 变量名:集合名/数组名){//...}
四、泛型
4.1 概念
泛型是一种未知的数据类型,但我们不知道使用什么数据类型的时候,就用泛型。
也可以看成一种变量,用来接收数据类型。

创建集合对象,不使用泛型时:
好处:集合不适用泛型,默认的类型就是Object类型,可以存储任意类型的数据
弊端:不安全,会引发异常。
创建集合对象,使用泛型:
- 好处:避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型;把运行期异常(代码运行之后抛出的异常),提升到了编译期(写代码的时候报错)。
- 弊端:泛型是什么类型,只能存储什么类型。
4.2 含有泛型的类
在定义类时在类名后面加个,创建对象时声明E是什么类型即可。
public class GenericClass<E> {private E name;public E getName() {return name;}public void setName(E name) {this.name = name;}}
public class Demo02GenericClass {public static void main(String[] args) {//不写泛型默认为Object类型GenericClass gc = new GenericClass();gc.setName("test");Object obj = gc.getName();//创建GenericClass对象,泛型使用Integer类型GenericClass<Integer> gc2 = new GenericClass<>();gc2.setName(1);Integer name = gc2.getName();System.out.println(name);//创建GenericClass对象,泛型使用String类型GenericClass<String> gc3 = new GenericClass<>();gc3.setName("小明");String name1 = gc3.getName();System.out.println(name1);}}
4.3 含有泛型的方法
泛型定义在方法的 修饰符 和 返回值 类型之间
修饰符<泛型> 返回值类型 方法名(参数列表(使用泛型)){//方法体}
在调用时,要确认数据类型。
public class GenericMethod {//定义一个含有泛型的方法public <M> void method01(M m){System.out.println(m);}}
public class Demo03GenericMethod {public static void main(String[] args) {//创建GenericMethod对象GenericMethod gm = new GenericMethod();/*调用含有泛型的方法method01传递什么类型,泛型就是什么类型*/gm.method01(10);gm.method01("abc");gm.method01(8.8);gm.method01(true);}}
4.4 含有泛型的接口
public interface GenericInterface<I> {public abstract void method(I i);}
第一种使用方式 :定义接口的实现类,实现接口,指定接口的泛型。
public class GenericInterfaceImpl1 implements GenericInterface<String>{@Overridepublic void method(String s) {System.out.println(s);}}
第二种使用方式 :接口使用什么泛型,实现类就使用什么泛型,类跟着接口走,就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型。
// 这里的泛型必须保持一致为同一个名称(如:同为I),否则会报错public class GenericInterfaceImpl2<I> implements GenericInterface<I> {@Overridepublic void method(I i) {System.out.println(i);}}
public class Demo04GenericInterface {public static void main(String[] args) {//创建GenericInterfaceImpl1对象GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();gi1.method("字符串");//创建GenericInterfaceImpl2对象GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();gi2.method(10);GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();gi3.method(8.8);}}
4.5 泛型通配符
① 概念
不能创建对象使用,只能作为方法的参数使用。
public class Demo05Generic {public static void main(String[] args) {ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(2);ArrayList<String> list02 = new ArrayList<>();list02.add("a");list02.add("b");printArray(list01);printArray(list02);//ArrayList<?> list03 = new ArrayList<?>();//报错}/*定义一个方法,能遍历所有类型的ArrayList集合这时候我们不知道ArrayList集合使用什么数据类型,可以泛型的通配符?来接收数据类型注意:泛型是没有继承概念的,所以?不能用Object来代替*/public static void printArray(ArrayList<?> list){//使用迭代器遍历集合Iterator<?> it = list.iterator();while(it.hasNext()){//it.next()方法,取出的元素是Object,可以接收任意的数据类型Object o = it.next();System.out.println(o);}}}
② 受限泛型
- 泛型的上限限定:
? extends E代表使用的泛型只能是E类型的子类/本身 - 泛型的下限限定:
? super E代表使用的泛型只能是E类型的父类/本身
public class Demo06Generic {public static void main(String[] args) {Collection<Integer> list1 = new ArrayList<Integer>();Collection<String> list2 = new ArrayList<String>();Collection<Number> list3 = new ArrayList<Number>();Collection<Object> list4 = new ArrayList<Object>();getElement1(list1);//getElement1(list2);//报错getElement1(list3);//getElement1(list4);//报错//getElement2(list1);//报错//getElement2(list2);//报错getElement2(list3);getElement2(list4);/*类与类之间的继承关系Integer extends Number extends ObjectString extends Object*/}// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类public static void getElement1(Collection<? extends Number> coll){}// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类public static void getElement2(Collection<? super Number> coll){}}
五、List接口
java.util.List 有序、有索引、允许存储相同的元素
5.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 LinkedList
java.util.LinkedList
- ArrayList集合:底层是 数组结构 ,多线程,查询快,增删慢。
- LinkedList集合:① 底层是一个 链表结构 ,多线程,查询慢,增删快;② 里面包含了大量操作首尾元素的方法。
注意:使用LinkedList集合特有的方法,不能使用多态。
① 添加相关的方法
public void addFirst(E e) 将指定元素添加到此列表的开头,此方法等效于public void push(E e)方法public void addLast(E e) 将指定元素添加到此列表的结尾,此方法等效于add()
② 获取相关的方法
public E getFirst() 返回列表的第一个元素public E getLast() 返回列表的最后一个元素
注意:如果集合中无元素,会报错。
③ 移除相关的方法
public E removeFirst() 移除并返回此列表的第一个元素,等效于public E pop()public E removeLast() 移除并返回此列表的最后一个元素
5.3 Vector
底层是 数组结构 ,单线程,速度慢,后来被ArrayList取代。
六 、Set接口
java.util.Set
6.1 特点
① 不允许存储重复的元素。
② 没有索引,没有带索引的方法,也不能使用普通的for循环。
6.2 hashSet
6.2.1 特点
① 不允许存储重复的元素。
② 没有索引,没有带索引的方法,也不能使用普通的for循环。
③ 无序集合,存储元素和取出元素的顺序有可能不一致。
④ 底层是一个哈希表结构(查询的速度非常快)。
6.2.2 哈希值
哈希值是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来的地址,不是数据实际存储的物理地址)。
在Object类中有一个方法,可以获取对象的hash值
int hashCode()返回该对象的哈希码值
对象的地址值就是用的hashCode()方法返回的哈希码的十六进制,但是字符串String类重写了hashCode方法。
6.2.3 哈希表
在jdk1.8版本之前,哈希表 = 数组 + 链表
在jdk1.8版本之后:
哈希表 = 数组 +链表
哈希表 = 数组 + 红黑树(提高查询的速度)

Set集合不允许存储重复元素的原理:

6.2.4 存储引用类型
要求:同名和同年龄的人,视为同一个人,只能在Hashset集合中存储一次。
则必须重写hashCode方法和equals方法。
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;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}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 Demo03HashSetSavePerson {public static void main(String[] args) {//创建HashSet集合存储PersonHashSet<Person> set = new HashSet<>();Person p1 = new Person("小美女",18);Person p2 = new Person("小美女",18);Person p3 = new Person("小美女",19);System.out.println(p1.hashCode());//1967205423System.out.println(p2.hashCode());//42121758System.out.println(p1==p2);//falseSystem.out.println(p1.equals(p2));//true,若不重写,Object类中的equals方法和“==”是一样的,比较的都是内存地址值set.add(p1);set.add(p2);set.add(p3);System.out.println(set);}}
6.3 LinkedHashSet
java.util.LinkedHashSet 集合继承了HashSet集合
① 底层是一个哈希表(数组+链表/红黑树)+ 链表,比HashSet多了一条链表(记录元素的存储顺序),保证元素有序。
② 有序,不允许重复
七、可变参数
JDK1.5之后的新特性
7.1 使用格式
- 当方法的参数列表数据类型已经确定,但是参数个数不确定,就可以使用可变参数。
修饰符 返回值类型 方法名(数据类型...变量名){}
7.2 原理
可变参数的底层就是一个数组,根据传递参数个数的不同,会创建不同长度的数组,来存储这些参数,传递的参数个数,可以是0个(不传递),1个,2个…多个。
这样这个参数列表中的变量名就就变成了相应类型的数组。
public static int add(int...arr){//定义一个初始化的变量,记录累加求和int sum = 0;//遍历数组,获取数组中的每一个元素for (int i : arr) {//累加求和sum += i;}//把求和结果返回return sum;}
7.3 注意
① 一个方法的参数列表只能有一个可变参数
② 如果一个方法的参数有多个,那么可变参数必须写在参数列表的末尾。
7.4 特殊写法
public static void method(Object...obj){}//这里可以接收任意数据类型的参数
八、Collections工具类
java.util.Collections
public static <T> boolean addAll(Collection<T> c,T...elements)//往集合中添加一些元素public static void shuffle(List<?> list) //打乱集合顺序
排序方法
public static <T> void sort(List<T> list) //将集合中的元素按照默认规则进行排序
这里的 T 类型的数据,必须实现Comparable接口,并在类中重写接口中的方法compareTo定义。
Comparable接口的排序规则:
- 自己(this) - 参数 //这是升序
- 参数 - 自己(this)//这是降序
public class Person implements Comparable<Person>{private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}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;}//重写排序的规则@Overridepublic int compareTo(Person o) {//return 0;//认为元素都是相同的//自定义比较的规则,比较两个人的年龄(this,参数Person)//return this.getAge() - o.getAge();//年龄升序排序return o.getAge() - this.getAge();//年龄降序排序}}
public class Demo02Sort {public static void main(String[] args) {ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(3);list01.add(2);System.out.println(list01);//[1, 3, 2]//public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。Collections.sort(list01);//默认是升序System.out.println(list01);//[1, 2, 3]ArrayList<String> list02 = new ArrayList<>();list02.add("a");list02.add("c");list02.add("b");System.out.println(list02);//[a, c, b]Collections.sort(list02);System.out.println(list02);//[a, b, c]ArrayList<Person> list03 = new ArrayList<>();list03.add(new Person("张三",18));list03.add(new Person("李四",20));list03.add(new Person("王五",15));System.out.println(list03);//[Person{name='张三', age=18}, Person{name='李四', age=20}, Person{name='王五', age=15}]Collections.sort(list03);System.out.println(list03);}}
public static <T> void sort(List<T> list,Comparator<? super T>) //将集合中元素按照指定规则排序
Comparator 与 Comparable的区别
① Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则comparaTo方法
② Comparator:相当于找一个第三方的裁判,来进行比较(需要重写compare方法)
Comparator排序规则:
- 第一个参数 - 第二个参数 //升序
- 第二个参数 - 第一个参数 //降序
public class Demo03Sort {public static void main(String[] args) {ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(3);list01.add(2);System.out.println(list01);//[1, 3, 2]Collections.sort(list01, new Comparator<Integer>() {//重写比较的规则@Overridepublic int compare(Integer o1, Integer o2) {//return o1-o2;//升序return o2-o1;//降序}});System.out.println(list01);ArrayList<Student> list02 = new ArrayList<>();list02.add(new Student("a迪丽热巴",18));list02.add(new Student("古力娜扎",20));list02.add(new Student("杨幂",17));list02.add(new Student("b杨幂",18));System.out.println(list02);/*Collections.sort(list02, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {//按照年龄升序排序return o1.getAge()-o2.getAge();}});*///扩展:了解Collections.sort(list02, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {//按照年龄升序排序int result = o1.getAge()-o2.getAge();//如果两个人年龄相同,再使用姓名的第一个字比较if(result==0){result = o1.getName().charAt(0)-o2.getName().charAt(0);}return result;}});System.out.println(list02);}}
九、Map接口
java.util.Map public interface Map<K,V>
9.1 特点
① Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)。
② Map集合中的元素,key和value的数据类型可以相同也可以不同。
③ Map集合中的元素,key是不允许重复的,value是可以重复的。
④ Map集合中的元素,key和value是一一对应的。
9.1.1 HashMap
java.util.HashMap
① HashMap底层是哈希表,查询的速度特别快。
JDK1.8之前:数组 + 单向链表。JDK1.8之后:数组 + 单向链表/红黑树(链表的长度超过8):提高查询速度
② HashMap是一个无序集合,存储元素和取出元素的顺序有可能不一致。
9.1.2 LinkedHashMap
java.util.LinkedHashMap
① LinkedHashMap集合底层是哈希表+链表(保证迭代顺序)
② LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的。
9.2 Map常用方法
① put方法
public V put(K key , V value) //把指定的键值对添加到Map集合中
如果key已存在,返回null;如果不存在,则用新的value替换旧的value,返回旧的value值。
② remove方法
public V remove (Object key) //把指定的键值对元素,在Map中删除,返回被删除的元素的值
如果key存在,则返回被删除的值;如果key不存在,则返回null。
③ get方法
public V get(Object key) //根据指定的键,在Map集合中获取对应的值
如果key存在,返回对应的value值;如果key不存在,则返回null。
④ containsKey方法
boolean containsKey(Object key) //是否存在指定key
如果key存在,返回true;如果key不存在,则返回false。
⑤ keySet方法
Set<K> keySet() //返回次映射中包含的键的Set集合
9.3 Map的遍历
9.3.1 keySet()
Map集合的第一种遍历方式,通过键找值的方式:
public class Demo02KeySet {public static void main(String[] args) {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("赵丽颖",168);map.put("杨颖",165);map.put("林志玲",178);//1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中Set<String> set = map.keySet();//2.遍历set集合,获取Map集合中的每一个key//使用迭代器遍历Set集合Iterator<String> it = set.iterator();while (it.hasNext()){String key = it.next();//3.通过Map集合中的方法get(key),通过key找到valueInteger value = map.get(key);System.out.println(key+"="+value);}System.out.println("-------------------");//使用增强for遍历Set集合for(String key : set){//3.通过Map集合中的方法get(key),通过key找到valueInteger value = map.get(key);System.out.println(key+"="+value);}System.out.println("-------------------");//使用增强for遍历Set集合for(String key : map.keySet()){//3.通过Map集合中的方法get(key),通过key找到valueInteger value = map.get(key);System.out.println(key+"="+value);}}}
9.3.2 entrySet()
Entry是Map的内部类
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的Set集合
Map集合的第二种遍历方式,通过Entry对象遍历:
public class Demo03EntrySet {public static void main(String[] args) {//创建Map集合对象Map<String,Integer> map = new HashMap<>();map.put("赵丽颖",168);map.put("杨颖",165);map.put("林志玲",178);//1.使用Map集合中 的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中Set<Map.Entry<String, Integer>> set = map.entrySet();//2.遍历Set集合,获取每一个Entry对象//使用迭代器遍历Set集合Iterator<Map.Entry<String, Integer>> it = set.iterator();while(it.hasNext()){Map.Entry<String, Integer> entry = it.next();//3.使用Entry对象中的方法getKey()和getValue()获取键与值String key = entry.getKey();Integer value = entry.getValue();System.out.println(key+"="+value);}System.out.println("-----------------------");for(Map.Entry<String,Integer> entry:set){//3.使用Entry对象中的方法getKey()和getValue()获取键与值String key = entry.getKey();Integer value = entry.getValue();System.out.println(key+"="+value);}}}
9.4 存储引用类型
Map集合保证key是唯一的:
作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一。
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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}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 Demo01HashMapSavePerson {public static void main(String[] args) {show02();}private static void show02() {//创建HashMap集合HashMap<Person,String> map = new HashMap<>();//往集合中添加元素map.put(new Person("女王",18),"英国");map.put(new Person("秦始皇",18),"秦国");map.put(new Person("普京",30),"俄罗斯");map.put(new Person("女王",18),"毛里求斯");//使用entrySet和增强for遍历Map集合Set<Map.Entry<Person, String>> set = map.entrySet();for (Map.Entry<Person, String> entry : set) {Person key = entry.getKey();String value = entry.getValue();System.out.println(key+"-->"+value);}}private static void show01() {//创建HashMap集合HashMap<String,Person> map = new HashMap<>();//往集合中添加元素map.put("北京",new Person("张三",18));map.put("上海",new Person("李四",19));map.put("广州",new Person("王五",20));map.put("北京",new Person("赵六",18));//使用keySet加增强for遍历Map集合Set<String> set = map.keySet();for (String key : set) {Person value = map.get(key);System.out.println(key+"-->"+value);}}}
9.5 HashTable
java.util.HashTable
- 与HashMap的区别:
① 线程
HashTable:底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢。
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
② null
HashTable:不能存储null值、null键
HashMap(以及之前学的所有集合):可以存储null值、null键
- 过时:
HashTable 和 Vector 一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了。
但是HashTable的子类Properties依然活跃,Properties集合是一个唯一和IO流相结合的集合。
十、练习
10.1 斗地主

public class Dou {public static void main(String[] args) {ArrayList<String> card = saveCard();// System.out.println(card.size());// System.out.println(card);ArrayList<String> player1 = new ArrayList<>();ArrayList<String> player2 = new ArrayList<>();ArrayList<String> player3 = new ArrayList<>();ArrayList<String> bottom = new ArrayList<>();deliverCard(player1,player2,player3,bottom,card);System.out.println("刘德华:" + player1);System.out.println("周星驰:" + player2);System.out.println("古天乐:" + player3);System.out.println("底牌:" + bottom);// showCard(player1);// showCard(player2);// showCard(player3);// showCard(bottom);}//存牌并打乱public static ArrayList<String> saveCard(){ArrayList<String> card = new ArrayList<>();String[] color = {"♥","♦","♣","♠"};String[] tag = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};for (int i = 0; i < color.length; i++) {for (int j = 0; j < tag.length; j++) {card.add(color[i] + tag[j]);}}card.add("大王");card.add("小王");Collections.shuffle(card);//随机打乱集合中的元素return card;}//发牌public static void deliverCard(ArrayList<String> player1,ArrayList<String> player2,ArrayList<String> player3,ArrayList<String> bottom,ArrayList<String> card){for (int i = 0; i < card.size(); i++) {if(i > 50){bottom.add(card.get(i));}else{if(i % 3 == 0){player1.add(card.get(i));}if(i % 3 == 1){player2.add(card.get(i));}if(i % 3 == 2){player3.add(card.get(i));}}}}//看牌public static void showCard(ArrayList<String> cardlist){for (int i = 0; i < cardlist.size(); i++) {System.out.print(cardlist.get(i) + "\t\t");}System.out.println();}}
10.2 字符个数
计算一个字符串中的每个字符个数

public class CalcuChar {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入一个字符串:");String s = sc.nextLine();HashMap<Character,Integer> map = new HashMap<>();char[] charArray = s.toCharArray();for (int i = 0; i < charArray.length; i++) {if(map.containsKey(charArray[i])){map.put(charArray[i],map.get(charArray[i]) + 1);}else map.put(charArray[i],1);}// Set<Map.Entry<Character,Integer>> en = map.entrySet();for (Map.Entry<Character,Integer> en:map.entrySet()) {System.out.print(en.getKey() + ":");System.out.print(en.getValue());System.out.println();}}}
10.3 斗地主升级版

/*斗地主综合案例:有序版本1.准备牌2.洗牌3.发牌4.排序5.看牌*/public class DouDiZhu {public static void main(String[] args) {//1.准备牌//创建一个Map集合,存储牌的索引和组装好的牌HashMap<Integer,String> poker = new HashMap<>();//创建一个List集合,存储牌的索引ArrayList<Integer> pokerIndex = new ArrayList<>();//定义两个集合,存储花色和牌的序号List<String> colors = List.of("♠", "♥", "♣", "♦");List<String> numbers = List.of("2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");//把大王和小王存储到集合中//定义一个牌的索引int index = 0;poker.put(index,"大王");pokerIndex.add(index);index++;poker.put(index,"小王");pokerIndex.add(index);index++;//循环嵌套遍历两个集合,组装52张牌,存储到集合中for (String number : numbers) {for (String color : colors) {poker.put(index,color+number);pokerIndex.add(index);index++;}}//System.out.println(poker);//System.out.println(pokerIndex);/*2.洗牌使用Collections中的方法shuffle(List)*/Collections.shuffle(pokerIndex);//System.out.println(pokerIndex);/*3.发牌*///定义4个集合,存储玩家牌的索引,和底牌的索引ArrayList<Integer> player01 = new ArrayList<>();ArrayList<Integer> player02 = new ArrayList<>();ArrayList<Integer> player03 = new ArrayList<>();ArrayList<Integer> diPai = new ArrayList<>();//遍历存储牌索引的List集合,获取每一个牌的索引for (int i = 0; i <pokerIndex.size() ; i++) {Integer in = pokerIndex.get(i);//先判断底牌if(i>=51){//给底牌发牌diPai.add(in);}else if(i%3==0){//给玩家1发牌player01.add(in);}else if(i%3==1){//给玩家2发牌player02.add(in);}else if(i%3==2){//给玩家3发牌player03.add(in);}}/*4.排序使用Collections中的方法sort(List)默认是升序排序*/Collections.sort(player01);Collections.sort(player02);Collections.sort(player03);Collections.sort(diPai);/*5.看牌调用看牌的方法*/lookPoker("刘德华",poker,player01);lookPoker("周润发",poker,player02);lookPoker("周星驰",poker,player03);lookPoker("底牌",poker,diPai);}/*定义一个看牌的方法,提高代码的复用性参数:String name:玩家名称HashMap<Integer,String> poker:存储牌的poker集合ArrayList<Integer> list:存储玩家和底牌的List集合查表法:遍历玩家或者底牌集合,获取牌的索引使用牌的索引,去Map集合中,找到对应的牌*/public static void lookPoker(String name,HashMap<Integer,String> poker,ArrayList<Integer> list){//输出玩家名称,不换行System.out.print(name+":");//遍历玩家或者底牌集合,获取牌的索引for (Integer key : list) {//使用牌的索引,去Map集合中,找到对应的牌String value = poker.get(key);System.out.print(value+" ");}System.out.println();//打印完每一个玩家的牌,换行}}
十一、JDK9的新特性
List、Set、Map接口添加了一个静态方法of,可以给集合一次性添加多个元素。
static <E> List<E> of (E...elements)
使用前提: 当集合中存储的元素的个数已经确定了,不再改变时使用。
注意:
① of 方法只适用于List接口,Set接口,Map接口,不适用于这些接口的实现类。
② of 方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会出现异常。
③ Set接口和Map接口在调用方法时,不能有重复的元素,否则会抛出异常。
public class Demo01JDK9 {public static void main(String[] args) {List<String> list = List.of("a", "b", "a", "c", "d");System.out.println(list);//[a, b, a, c, d]//list.add("w");//UnsupportedOperationException:不支持操作异常//Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法参数异常,有重复的元素Set<String> set = Set.of("a", "b", "c", "d");System.out.println(set);//set.add("w");//UnsupportedOperationException:不支持操作异常//Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20,"张三",19);////IllegalArgumentException:非法参数异常,有重复的元素Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);System.out.println(map);//{王五=20, 李四=19, 张三=18}//map.put("赵四",30);//UnsupportedOperationException:不支持操作异常}}
十二、Debug调试
使用方式:
在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里),右键,选择Debug执行程序,程序就会停留在添加的第一个断点处。
执行程序:
- f8:逐行执行程序
- f7:进入到方法中
- shift+f8:跳出方法
- f9:跳到下一个断点,如果没有下一个断点,那么就结束程序
- ctrl+f2:退出debug模式,停止程序
- Console:切换到控制台
