Java基础2
Exception 异常
ExceptionDemo1.java 时间日期异常、文件异常
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo1{
public static void main(String[] args){
try {
//监视代码,出现异常,会被catch拦截住这个异常
show2();
} catch (ParseException e) {
e.printStackTrace();// 打印异常信息
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static void show2() throws ParseException, FileNotFoundException {
System.out.println("-----show2() run-----");
//编译异常:编译阶段报错,编译不通过。
String str = "2024-07-29 11:45:14";//定义时间字符串str,格式为"yyyy-MM-dd HH:mm:ss"。
//把字符串时间解析成Java中的一个日期对象。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//创建SimpleDateFormat对象sdf,指定与字符串匹配的格式。
//sdf.parse() 将字符串 "2024-07-29 11:45:14" 转换为 Date 对象(内部存储为时间戳)
//java.util.Date 对象的 toString() 方法会返回一个固定格式的字符串: "EEE MMM dd HH:mm:ss zzz yyyy"
//EEE:星期缩写(如 Mon)
//MMM:月份缩写(如 Jul)
//zzz:时区(如 CST,中国标准时间)
Date date = sdf.parse(str);//编译时异常,提醒这里的程序很容易出错 //调用sdf.parse()方法将字符串解析为Date对象date(需处理ParseException异常)
System.out.println(date);//Mon Jul 29 11:45:14 CST 2024
InputStream is = new FileInputStream("D:/bafafbjzfka.png");
System.out.println("-----show2() over-----");
}
}
res
-----show2() run----- Mon Jul 29 11:45:14 CST 2024 java.io.FileNotFoundException: D:\bafafbjzfka.png (系统找不到指定的文件。) at java.base/java.io.FileInputStream.open0(Native Method) at java.base/java.io.FileInputStream.open(FileInputStream.java:211) at java.base/java.io.FileInputStream.<init>(FileInputStream.java:153) at java.base/java.io.FileInputStream.<init>(FileInputStream.java:108) at com.itheima.demo1_exception.ExceptionDemo1.show2(ExceptionDemo1.java:39) at com.itheima.demo1_exception.ExceptionDemo1.main(ExceptionDemo1.java:14)
ExceptionDemo2.java
public class ExceptionDemo2 {
public static void main(String[] args) {
//异常是用来定位程序bug的关键信息,可以作为方法内部的一种特殊返回值,以便通知上层调用者,方法的执行问题
//Exception,分为两类:编译时异常、运行时异常。
//编译时异常:没有继承RuntimeException的异常,编译阶段就会出错。
//运行时异常:继承自RuntimeException的异常或其子类,编译阶段不报错,运行时出现的
System.out.println("main方法开始");
try {
int result = div(10, 0);
System.out.println("div()执行成功");
}
catch (Exception e){
System.out.println(e.getMessage());//除数不能为0
e.printStackTrace();//红字打印异常信息
System.out.println("div()执行失败");
}
System.out.println("main方法结束");
}
public static int div(int a, int b) throws Exception{
if(b == 0){
//System.out.println("除数不能为0");
throw new Exception("除数不能为0");
}
int result = a / b;
return result;
}
}
res
main方法开始 除数不能为0 div()执行失败 main方法结束 java.lang.Exception: 除数不能为0 at com.itheima.demo1_exception.ExceptionDemo2.div(ExceptionDemo2.java:25) at com.itheima.demo1_exception.ExceptionDemo2.main(ExceptionDemo2.java:11)
ExceptionDemo3.java
两种自定义异常。一种编译时异常,另一种运行时异常。
//Java无法为这个世界上全部的问题都提供异常类来代表,如果企业自己的某种问题想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了
public class ExceptionDemo3 {
public static void main(String[] args) { test1();test2(); }
public static void test2(){
//目标:认识自定义异常类
System.out.println("test2()开始");
try {
saveAge2(500);
System.out.println("saveAge2()执行成功");
} catch (AgeRuntimeException e) {
e.printStackTrace();
System.out.println("年龄不合理");
}
System.out.println("test2()结束");
}
public static void test1(){
//目标:认识自定义异常类
System.out.println("test1()开始");
try {
saveAge(500);
System.out.println("saveAge()执行成功");
} catch (AgeException e) {
e.printStackTrace();
System.out.println("年龄不合理");
}
System.out.println("test1()结束");
}
//需求:我们公司的系统只要收到了年龄小于1岁或者大于200岁就是一个年龄非法异常
public static void saveAge2(int age) throws AgeRuntimeException{
if(age<1 || age>200){
//自定义异常类
throw new AgeRuntimeException("年龄非法异常");
}else{
System.out.println("年龄合法");
}
}
//需求:我们公司的系统只要收到了年龄小于1岁或者大于200岁就是一个年龄非法异常
public static void saveAge(int age) throws AgeException{
if(age<1 || age>200){
//自定义异常类
throw new AgeException("年龄非法异常");
}else{
System.out.println("年龄合法");
}
}
}
//自定义 编译时异常类
//1.继承Exception类
//2.重写Exception类的构造方法
//3.哪里需要用这个异常返回,哪里就抛这个异常
class AgeException extends Exception {
public AgeException() { }
public AgeException(String message) { super(message); }
}
//自定义 运行时异常类
//1.继承RuntimeException类
//2.重写RuntimeException类的构造方法
//3.哪里需要用这个异常返回,哪里就抛这个异常
class AgeRuntimeException extends RuntimeException {
public AgeRuntimeException() { }
public AgeRuntimeException(String message) { super(message); }
}
res
test1()开始 年龄不合理 test1()结束 test2()开始 年龄不合理 test2()结束 com.itheima.demo1_exception.AgeException: 年龄非法异常 at com.itheima.demo1_exception.ExceptionDemo3.saveAge(ExceptionDemo3.java:46) at com.itheima.demo1_exception.ExceptionDemo3.test1(ExceptionDemo3.java:23) at com.itheima.demo1_exception.ExceptionDemo3.main(ExceptionDemo3.java:5) com.itheima.demo1_exception.AgeRuntimeException: 年龄非法异常 at com.itheima.demo1_exception.ExceptionDemo3.saveAge2(ExceptionDemo3.java:36) at com.itheima.demo1_exception.ExceptionDemo3.test2(ExceptionDemo3.java:11) at com.itheima.demo1_exception.ExceptionDemo3.main(ExceptionDemo3.java:5)
ExceptionDemo5.java
package com.itheima.demo1_exception;
import java.util.Scanner;
public class ExceptionDemo5 {
public static void main(String[] args) {
//目标:掌握异常的处理方案 1: 底层异常都抛出去给最外层调用者,最外层捕获异常,记录异常,响应合适信息给用户观看。
// 2:捕获异常对象,尝试重新修复。
// 接收用户的一个定价
System.out.println("main()开始");
while(true){
try{
double price = userInputPrice();
System.out.println("正确输入价格");
break;
} catch (Exception e){
//e.printStackTrace();
System.out.println("价格输入有误,请重新输入");
}
}
System.out.println("main()结束");
}
public static double userInputPrice() {
// 1.接收用户的一个定价
System.out.println("请输入一个价格:");
Scanner sc = new Scanner(System.in);
double price = sc.nextDouble();
return price;
}
}
Genericity 泛型
GenericDemo2.java 自定义list
import java.util.ArrayList;
public class GenericDemo2 {
public static void main(String[] args) {
//目标:学会自定义泛型类。
//需求:请您模拟ArrayList集合自定义一个集合MyArrayList
//MyArrayList<String> list = new MyArrayList<String>();
MyArrayList<String> list = new MyArrayList<>();//JDK7 的新特性,可以省略掉<String>
list.add("hello");
list.add("world");
for ( int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
}
}
class MyArrayList<E> {
private E[] array;//array.length代表当前list占据多少空间
private int size;//记录当前集合中有多少个有效的元素
public MyArrayList() { array = (E[]) new Object[10]; }
public int size() {return size;}
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("OUT OF RANGE");
}
return array[index];
}
public void add(E e) {
if (size == array.length) {
E[] newArray = (E[]) new Object[array.length + 10];
System.arraycopy(array, 0, newArray, 0, array.length);//第2个srcPos代表源阵列中的起始位置,第4个destPos代表目标数据中的起始位置
array = newArray;
}
array[size++] = e;
}
}
class MyArrayList2<E> {
private ArrayList list = new ArrayList();
public boolean add(E e) { return list.add(e); }
public boolean remove(E e) { return list.remove(e); }
@Override
public String toString() { return list.toString(); }
}
泛型接口的基本作用
需要对学生数据进行增删改查操作
Data.java
public interface Data<T> {
void add(T t);
void delete(T t);
void update(T t);
T query(int id);
}
Student.java
public class Student { }
StudentData.java
public class StudentData implements Data<Student>{
@Override
public void add(Student student) { }
@Override
public void delete(Student student) { }
@Override
public void update(Student student) { }
@Override
public Student query(int id) { return null; }
}
泛型方法
GenericDemo4.java
public class GenericDemo4 {
public static void main(String[] args) {
//目标:学会定义泛型方法,搞清楚作用。
//需求:打印任意数组的内容。
}
public static <T> void printArray(T[] arr) {
for (T t : arr) {
System.out.println(t);
}
}
public static <T> T get(T[] arr, int index) { return arr[index]; }
}
GenericDemo5.java 泛型方法的通配符和上下符
import java.util.ArrayList;
public class GenericDemo5 {
public static void main(String[] args) {
//目标:理解通配符和上下限。
//虽然Xiaomi和BYD是Car的子类,但是 ArrayList<Xiaomi> ArrayList<BYD>和 ArrayList<Car>是没有半毛钱关系
ArrayList<Xiaomi> xiaomiList = new ArrayList<>();
xiaomiList.add(new Xiaomi());
xiaomiList.add(new Xiaomi());
ArrayList<BYD> bydList = new ArrayList<>();
bydList.add(new BYD());
bydList.add(new BYD());
ArrayList<Dog> dogList = new ArrayList<>();
dogList.add(new Dog());
dogList.add(new Dog());
}
//集合并不知道 对象之间是不是有继承关系,只知道是3个数据类型,而数据类型不一样
//就是“?”可以在“使用泛型”的时候代表一切类型;ETKV是在定义泛型的时候使用
//泛型上限:?extends Car:?能接收的必须是Car或者其子类。
//泛型下限:?super Car:?能接收的必须是Car或者其父类。
public static void go(ArrayList<? extends Car> cars){
//限定泛型的使用,只能是Car或者Car的子类。防止Dog类也跑进来使用
}
}
class Car{}
class Xiaomi extends Car{}
class BYD extends Car{}
class Dog {}
泛型包装拆箱基础类型
GenericDemo6.java
import java.util.ArrayList;
public class GenericDemo6 {
public static void main(String[] args) {
//目标:搞清楚泛型和集合不支持基本数据类型,只能支持对象类型(引用数据类型)。
//包装类就是把基本类型的数据包装成对象的类型。比如Integer包装了int,Double包装了double,Character包装了char
ArrayList<Integer> list = new ArrayList<>();
list.add(100);//自动装箱
//把基本数据类型变成包装类对象
//手工包装:
//Integer it = new Integer(100);//过时
Integer it1 = Integer.valueOf(100);//推荐
Integer it2 = Integer.valueOf(100);
System.out.println(it1 == it2);//true,-128~127范围,都是放在常量池。
Integer it3 =Integer.valueOf(200);
Integer it4 = Integer.valueOf(200);
System.out.println(it3 == it4);//false
//自动装箱:基本数据类型可以自动转换为包装类型。
//自动拆箱:包装类型可以自动转换为基本数据类型
Integer it11 = 100;//与Integer it1 = Integer.valueOf(100);作用完全一样
//包装类新增的功能:
//把基本类型的数据转换成字符串。
int j1 = 1;
String j1Str = Integer.toString(j1);//1.调用Integer.toString(intNum)转换为字符串
Integer j2 = 2;
String j2Str = j2.toString();//2.调用IntegerNum.toString()转换为字符串
int j3 = 3;
String j3Str = j3 + "";//3.intNum + ""转换为字符串
System.out.println("-----------------------");
String str = "123";
int strInt1 = Integer.parseInt(str);
int strInt2 = Integer.valueOf(str);
String str2 = "123.456";
double strDouble1 = Double.parseDouble(str2);
double strDouble2 = Double.valueOf(str2);
}
}
Collection 集合
CollectionDemo1.java
import java.util.*;
public class CollectionDemo1 {
public static void main(String[] args) {
/**
* 目标:搞清楚Collection集合的整体特点
* 1.List家族的集合:有序、可重复、有索引。
* 2.Set家族的集合:无序、不重复、无索引。
* 3.Map家族的集合:无序、不重复、键值对。
* 4.Collection集合:集合的顶级接口,没有直接的实现类,只定义了共性的方法。
* 5.Collection集合的实现类:ArrayList、LinkedList、Vector、HashSet、LinkedHashSet、TreeSet、HashMap、LinkedHashMap、TreeMap。
*/
//1.List家族的集合:有序、可重复、有索引。
List<String> list = new ArrayList<>();
list.add("Java");list.add("Java");list.add("C");list.add("C++");list.add("C#");
System.out.println(list);//[Java, Java, C, C++, C#]
//2.Set家族的集合:无序、不重复、无索引。
Set<String> set = new HashSet<>();
set.add("Java");set.add("Java");set.add("C");set.add("C++");set.add("C#");
System.out.println(set);//[C#, Java, C++, C]
}
}
Collection 通用功能
CollectionDemo2.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionDemo2 {
public static void main(String[] args) {
/**
* 目标:搞清楚Collection提供的通用集合功能
* Collection集合的通用功能:增删改查、遍历、判断、清空。
* 1.增:add(E e)
* 2.删:remove(Object o)
* 3.改:set(int index, E element)
* 4.查:get(int index)
* 5.遍历:
* a.迭代器:Iterator<E> iterator()
* b.foreach:for(E e:集合)
* c.普通for循环:for()
* 6.判断:contains(Object o)、isEmpty()、size()
* 7.清空:clear()
*/
Collection<String> list = new ArrayList<>();
list.add("Java");list.add("C");list.add("C++");list.add("C#");list.add("Python");
System.out.println(list.size());//5
System.out.println(list.contains("Java"));//true
System.out.println(list.isEmpty());// false
list.remove("C++");
System.out.println(list);//[Java, C, C#, Python]
//把集合中的元素全部取出来,放到数组中
Object[] arr = list.toArray();
System.out.println(Arrays.toString(arr));//[Java, C, C#, Python]
//把集合转换成字符串数组
String[] arr3 = list.toArray(size -> new String[size]);//根据集合大小创建对应长度的新数组
String[] arr2 = list.toArray(String[]::new);//lambda表达式
System.out.println(arr2);//打印的是地址 //[Ljava.lang.String;@3feba861
System.out.println(Arrays.toString(arr2));//[Java, C, C#, Python]
}
}
Collection 遍历
CollectionTraversalDemo3.java
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
public class CollectionTraversalDemo3 {
public static void main(String[] args) {
//目标:掌握Collection的遍历方式一:迭代器遍历
Collection<String> names = new ArrayList<>();
names.add("张三");names.add("李四");names.add("王五");names.add("赵六");
//1.得到这个集合的迭代器对象
Iterator<String> it = names.iterator();
/*System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());*/
//System.out.println(it.next());执行到这里会报错,因为迭代器已经遍历完了,没有元素了。
//2.使用while循环遍历
while (it.hasNext()) {
System.out.println(it.next());
}
//3.lambda遍历
names.forEach(new Consumer<String>() {
@Override
public void accept(String s) { System.out.println(s); }
});
names.forEach(s -> System.out.println(s));
names.forEach(System.out::println);
}
}
Collection 修改异常问题
CollectionTraversalTest6.java
import java.util.ArrayList;
import java.util.Iterator;
public class CollectionTraversalTest6 {
public static void main(String[] args) {
//目标:认识并发修改异常问题,搞清楚每种遍历的区别
ArrayList<String> list = new ArrayList<>();
list.add("java");list.add("宁夏枸杞");list.add("黑枸杞");list.add("人字拖");list.add("特级枸杞");list.add("枸杞子");list.add("西洋参");
//将list集合中的内容复制给一个新的集合list2
ArrayList<String> list2 = new ArrayList<>();
for (String s : list) {
list2.add(s);
}
/*//这样会漏删
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.contains("枸杞")) {
list.remove(s);
}
}
System.out.println(list);*/
//需求:删除全部枸杞
//解决方案:倒着遍历并删除(前提是支持索引)
for (int i = list.size() - 1; i >= 0; i--) {
String s = list.get(i);
if (s.contains("枸杞")) {
list.remove(s);
}
}
System.out.println(list);
//Java语言已经知道迭代器并发删除是有问题的,就不把产生问题的过程提上来了,直接写了个删除数据判定,一删除,就报错,就完了~
//方案一:迭代器遍历并删除默认也存在并发修改异常问题。
//方案二和三:用增强for还有Lambda(都没有办法解决并发修改异常问题)
//可以解决:使用选代器自己的方法来删除
System.out.println(list2);
Iterator<String> it2 = list2.iterator();
while(it2.hasNext()){
String name = it2.next();
if(name.contains("枸杞")){
//list2.remove(name);报错
it2.remove();
}
}
System.out.println(list2);
}
}
List
ArrayList
ListDemo1.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
public class ListDemo1 {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("张三");names.add("李四");names.add("王五");names.add("赵六");names.add("田七");names.add("王八");
names.add(2,"哈基磊");//给定下标位置插入
names.add(4,"哈基米");
names.add(0,"哈基汪");
System.out.println(names);//[哈基汪, 张三, 李四, 哈基磊, 王五, 哈基米, 赵六, 田七, 王八]
names.remove(4);//删除指定下标位置的元素
names.remove("李四");//删除指定元素
System.out.println(names);//[哈基汪, 张三, 哈基磊, 哈基米, 赵六, 田七, 王八]
System.out.println(names.set(1,"哈基人"));//根据下标修改,返回修改前的数据 //张三
System.out.println(names);//[哈基汪, 哈基人, 哈基磊, 哈基米, 赵六, 田七, 王八]
System.out.println(names.get(2));//根据下标获取元素 //哈基磊
System.out.println("--------------------------");
for(int i = 0; i < names.size(); i++){
System.out.println(names.get(i));
}
System.out.println("--------------------------");
for(String name : names){
System.out.println(name);
}
System.out.println("--------------------------");
names.forEach(name -> System.out.println(name));
System.out.println("--------------------------");
Iterator<String> it = names.iterator();
while(it.hasNext()){
String name = it.next();
System.out.println(name);
}
}
}
ListDemo2.java
import java.util.LinkedList;
import java.util.List;
public class ListDemo2 {
public static void main(String[] args) {
//目标:用LinkedList实现一个队列。
LinkedList<String> queue = new LinkedList<>();
queue.addLast("张三");queue.addLast("李四");queue.addLast("王五");queue.addLast("赵六");queue.addLast("田七");
System.out.println(queue);//[张三, 李四, 王五, 赵六, 田七]
System.out.println(queue.removeFirst());//张三
System.out.println(queue.removeFirst());//李四
System.out.println("---------------------");
//实现一个栈
LinkedList<String> stack = new LinkedList<>();
//压栈
stack.addFirst("张三");//放到序列第一个位置
stack.addFirst("李四");
stack.addFirst("王五");
stack.addFirst("赵六");
stack.push("田七");//放到序列第一个位置
System.out.println(stack);//[田七, 赵六, 王五, 李四, 张三]
System.out.println(stack.removeFirst());//田七
System.out.println(stack.pop());//赵六
System.out.println(stack);//[王五, 李四, 张三]
}
}
demo8_MovieSys
Movie.java
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Movie { private String name; private String actor; private double price; private double score; }
MovieService.java
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class MovieService {
private static List<Movie> movies = new ArrayList<>();
private static Scanner sc = new Scanner(System.in);
public void start(){
while(true){
System.out.println("----电影信息操作系统----");
System.out.println("1.添加电影");
System.out.println("2.删除电影");
System.out.println("3.查询电影");
System.out.println("4.封杀明星");
System.out.println("5.展示全部电影");
System.out.println("6.修改电影");
System.out.println("7.退出系统");
System.out.println("请输入您的指令");
switch (sc.nextInt()){
case 1: addMovie();break;
case 2: deleteMovie();break;
case 3: queryMovie();break;
case 4: deleteStar();break;
case 5: showAllMovie();break;
case 6: modifyMovie();break;
case 7: return;
default: System.out.println("输入有误");
}
}
}
private void modifyMovie() {
System.out.println("请输入电影名称");
String name = sc.next();
Movie m = queryMovieByName(name);
if(m == null){
System.out.println("没有找到");return;
}
System.out.println("请输入修改后的演员");
m.setActor(sc.next());
System.out.println("请输入修改后的价格");
m.setPrice(sc.nextDouble());
System.out.println("请输入修改后的评分");
m.setScore(sc.nextDouble());
System.out.println("修改成功");
}
private void showAllMovie() {
for (Movie movie : movies) {
System.out.println(movie.getName()+" "+movie.getActor()+" "+movie.getPrice()+" "+movie.getScore());
}
}
private void deleteStar() {
System.out.println("请输入要封杀的明星名称");
String name = sc.next();
for(int i = 0; i < movies.size(); i++){
//注意:contains方法,判断字符串中是否包含某个字符,返回true或者false
// equals方法,判断字符串是否与某个字符完全相等,返回true或者false
if(movies.get(i).getActor().contains(name)){
movies.remove(i);
System.out.println("封杀成功");
i--;//删除一个元素,索引要往前移一位
}
}
}
private void deleteMovie() {
System.out.println("请输入电影名称");
String name = sc.next();
Movie m = queryMovieByName(name);
if(m != null){
movies.remove(m);
System.out.println("删除成功");return;
}
System.out.println("没有找到");
}
private void queryMovie() {
System.out.println("请输入电影名称");
String name = sc.next();
Movie m = queryMovieByName(name);
if(m != null){
System.out.println(m.getName()+" "+m.getActor()+" "+m.getPrice()+" "+m.getScore());return;
}
System.out.println("没有找到");
}
public Movie queryMovieByName(String name){
for (Movie movie : movies) {
if(movie.getName().equals(name)){
return movie;
}
}
return null;
}
private void addMovie() {
Movie m = new Movie();
System.out.println("请输入电影名称");
m.setName(sc.next());
System.out.println("请输入电影演员");
m.setActor(sc.next());
System.out.println("请输入电影价格");
m.setPrice(sc.nextDouble());
System.out.println("请输入电影评分");
m.setScore(sc.nextDouble());
movies.add(m);
System.out.println("添加成功");
}
}
Test.java
public class Test {
public static void main(String[] args) {
//目标:完成电影案例
//1、创建电影对象:定义电影类。
//2、创建一个电影操作对象:专门负责对象电影数据进行业务处理(上架,下架,查询,封杀某个电影明星的电影)
MovieService ms = new MovieService();
ms.start();
}
}
Set
SetDemo1.java
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo1 {
public static void main(String[] args) {
/**
* Set系列集合特点:无序:添加数据的顺序和获取出的数据顺序不一致; 不重复;无索引;
* HashSet:无序、不重复、无索引。
* LinkedHashset:有序、不重复、无索引。
* TreeSet:默认升序排序、不重复、无索引。
* Set要用到的常用方法,基本上就是Collection提供的
* 自己几乎没有额外新增一些常用功能!
*/
Set<String> set = new HashSet<>();//无序、不重复、无索引。
set.add("Java");set.add("Java");set.add("C");set.add("C++");set.add("C#");
System.out.println(set);//[C#, Java, C++, C]
System.out.println("--------------------");
Set<Integer> set2 = new LinkedHashSet<>();//有序、不重复、无索引。
set2.add(9);set2.add(1);set2.add(1);set2.add(4);set2.add(5);set2.add(1);set2.add(4);
System.out.println(set2);//按添加的顺序输出 //[9, 1, 4, 5]
System.out.println("--------------------");
Set<Double> set3 = new TreeSet<>();//默认升序排序、不重复、无索引。
set3.add(1.0);set3.add(9.0);set3.add(1.0);set3.add(9.0);set3.add(8.0);set3.add(1.0);set3.add(0.0);
System.out.println(set3);//0.0, 1.0, 8.0, 9.0]
System.out.println("--------------------");
System.out.println("123".hashCode());//48690
}
}
HashSet去重 重写对象hashCode方法和equals方法
SetDemo2.java
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class SetDemo2 {
public static void main(String[] args) {
//目标:掌握HashSet集合去重操作。
Student s1 = new Student("张三", 18, "北京", "123456");
Student s2 = new Student("李四", 19, "上海", "654321");
Student s3 = new Student("张三", 18, "北京", "123456");
Student s4 = new Student("李四", 19, "上海", "654321");
//结论:如果希望Set集合认为2个内容一样的对象是重复的
//必须重写对象的hashCode()和equals()方法
//默认的是拿对象(地址不同)生成hash。重写之后是拿属性值(属性相同)生成hash
Set<Student> set = new HashSet<>();
set.add(s1);set.add(s2);set.add(s3);set.add(s4);
System.out.println(set);
}
}
class Student{
private String name;
private int age;
private String address;
private String phone;
public Student(){}
public Student(String name, int age, String address, String phone) {
this.name = name;this.age = age;this.address = address;this.phone = phone;
}
@Override
public boolean equals(Object o) {
//判断对象是否是同一个对象,如果是同一个对象,则返回true
if (this == o) return true;
//如果对象为null,则返回false。判断对象是否是同一个类型,如果不是同一个类型,则返回false。
if (o == null || this.getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name) && Objects.equals(address, student.address) && Objects.equals(phone, student.phone);
}
/**
* 这段代码的功能是:
* 1. 重写Object类的hashCode()方法,为Student对象生成哈希值
* 2. 使用Objects.hash()方法,将对象的四个属性(name, age, address, phone)组合计算哈希值
* 3. 当这些属性值相同时,会返回相同的哈希码,用于哈希表等数据结构中快速比较对象
* @return
*/
@Override
public int hashCode() { return Objects.hash(name, age, address, phone); }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", phone='" + phone + '\'' +
'}' + "\n";
}
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 String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
}
res
[Student{name='张三', age=18, address='北京', phone='123456'} , Student{name='李四', age=19, address='上海', phone='654321'} ]
SetDemo3.java TreeSet
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo3 {
public static void main(String[] args) {
/**
* TreeSet集合特点:不重复、无索引、可排序(默认升序排序,按照元素的大小,由小到大排序)。底层是基于红黑树实现的排序,
* 对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序。对于字符串类型:默认按照首字符的编号升序排序。
* 对于自定义类型如Student对象,TreeSet默认是无法直接排序的
* 目标:搞清楚TreeSet集合对于自定义对象的排序
*/
Set<Teacher> t = new TreeSet<>();
t.add(new Teacher("小王", 20, 6324));
t.add(new Teacher("小叶", 18, 1145));
t.add(new Teacher("小李", 22, 1419));
t.add(new Teacher("小江", 20, 1981));
System.out.println(t);
//结论:TreeSet集合默认不能 给自定义对象排序啊,因为不知道大小规则。一定要能解决怎么办?两种方案。
//1.对象类实现一个Comparable比较接口,重写compareTo方法,指定大小比较规则
//2.public TreeSet(Comparator c)集合自带比较器Comparator对象,指定比较规则
Set<Teacher> t2 = new TreeSet<>(new Comparator<Teacher>() {
@Override
public int compare(Teacher o1, Teacher o2) {
/*
//按年龄降序排序
if(o2.getAge() > o1.getAge()) return 1;
else if(o2.getAge() < o1.getAge()) return -1;
return 1;*/
return Double.compare(o1.getSalary(), o2.getSalary());//按工资升序排序
}
});
Set<Teacher> t3 = new TreeSet<>((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary()));
t2.add(new Teacher("小王", 20, 6324));
t2.add(new Teacher("小叶", 18, 1145));
t2.add(new Teacher("小李", 22, 1419));
t2.add(new Teacher("小江", 20, 1981));
System.out.println(t2);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Teacher implements Comparable<Teacher> {
private String name;
private int age;
private double salary;
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}' + "\n";
}
//t2.compareTo(t1)
//t2 == this 比较者
//t1 == o 被比较者
//如果返回值小于0,则认为t2小于t1,t2在t1之前。
//如果返回值大于0,则认为t2大于t1,t2在t1之后。
//如果返回值等于0,则认为t2等于t1,t2和t1在同一位置。
@Override
public int compareTo(Teacher o) {
//按年龄升序排序
if (this.getAge() > o.getAge()) return 1;
else if (this.getAge() < o.getAge()) return -1;
return 1;//保证年龄相同的值不会被剔除
}
}
res
[Teacher{name='小叶', age=18, salary=1145.0} , Teacher{name='小王', age=20, salary=6324.0} , Teacher{name='小江', age=20, salary=1981.0} , Teacher{name='小李', age=22, salary=1419.0} ] [Teacher{name='小叶', age=18, salary=1145.0} , Teacher{name='小李', age=22, salary=1419.0} , Teacher{name='小江', age=20, salary=1981.0} , Teacher{name='小王', age=20, salary=6324.0} ]
Map
HashMap特点:无序,不重复,无索引,键值对都可以是null,值不做要求(可以重复)
LinkedMap特点:有序,不重复,无索引,键值对都可以是null,值不做要求(可以重复)
TreeMap:按照键可排序,不重复,无索引
MapDemo1.java
import java.util.HashMap;
import java.util.Map;
public class MapDemo1 {
public static void main(String[] args) {
//HashMap特点:无序,不重复,无索引,键值对都可以是null,值不做要求(可以重复)
//LinkedMap特点:有序,不重复,无索引,键值对都可以是null,值不做要求(可以重复)
//TreeMap:按照键可排序,不重复,无索引
Map<String,Integer> map = new HashMap<>();
map.put("小王",18);
map.put("小李",19);
map.put("小张",20);
map.put(null,null);
System.out.println(map);//{null=null, 小李=19, 小王=18, 小张=20}
}
}
MapDemo2.java Map遍历
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class MapDemo2 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("张三",18);map.put("李四",19);map.put("王五",20);map.put("赵六",21);map.put("田七",22);map.put("王八",23);map.put(null,null);
//map的常用方法
System.out.println(map.size());//7
System.out.println(map.isEmpty());//false
System.out.println(map.containsKey("张三"));//true
System.out.println(map.containsValue(18));//true
System.out.println(map.get("张三"));//获取键对应的值 //18
System.out.println(map.remove("张三"));//根据键删除键值对对象,并返回删除的value //18
System.out.println("--------------1--------------");
Set<String> keyS = map.keySet();//获取所有的键,保存到set集合中
for (String key : keyS) {
System.out.println(key + "-->" + map.get(key));
}
System.out.println("--------------2--------------");
/**
* Map.Entry 是 Java 中 Map 接口定义的静态嵌套接口(static nested interface),用于表示 Map 中的一个键值对(Key-Value Pair)。以下是关键点解析:
* 本质 是 Map 接口的内部接口:Map.Entry<K,V>
* 每个 Entry 对象代表 Map 中的一个键值对(如 {"张三": 18})
* 核心方法
* K getKey():返回键(如 "张三")
* V getValue():返回值(如 18)
* V setValue(V value):修改当前键值对的值(注意:直接修改会同步到原 Map)
* 使用场景
* 通过 map.entrySet() 获取所有 Entry 的集合(如示例中的遍历)
* 适合需要同时访问键和值的场景(比先取 keySet 再 get(key) 更高效)
* 其他特性
* 支持泛型(如 Map.Entry<String,Integer>)
* 是遍历 Map 的标准方式之一(尤其 JDK8 之前)
* 补充:在 JDK8+ 中,Map.forEach 和 Lambda 表达式(如 map.forEach((k,v) -> ...))可以更简洁地替代 Entry 遍历。
*/
//把Map集合转换成Set集合,里面的元素类型都是键值对类型(Map.Entry<String,Integer>)
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();//获取所有的键值对对象,保存到set集合中
for (Map.Entry<String, Integer> entry : entrySet) {
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
System.out.println("--------------3--------------");
//获取所有的值放到一个Collection集合中
Collection<Integer> values = map.values();
for (Integer value : values) {
System.out.println(value);
}
System.out.println("--------------4--------------");
map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
System.out.println(s + "-->" + integer);
}
});
System.out.println("--------------5--------------");
map.forEach((s, integer) -> System.out.println(s + "-->" + integer));
}
}
res
7 false true true 18 18 --------------1-------------- null-->null 李四-->19 王五-->20 赵六-->21 田七-->22 王八-->23 --------------2-------------- null-->null 李四-->19 王五-->20 赵六-->21 田七-->22 王八-->23 --------------3-------------- null 19 20 21 22 23 --------------4-------------- null-->null 李四-->19 王五-->20 赵六-->21 田七-->22 王八-->23 --------------5-------------- null-->null 李四-->19 王五-->20 赵六-->21 田七-->22 王八-->23
MapDemo7.java TreeMap
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
public class MapDemo7 {
public static void main(String[] args) {
//目标:TreeMap集合(原理和用法于TreeSet一样)
//Map<Teacher3,String> map = new TreeMap<>((o1, o2) -> Double.compare(o1.getSalary(),o2.getSalary()));
Map<Teacher3,String> map = new TreeMap<>(Comparator.comparingDouble(Teacher3::getSalary));
map.put(new Teacher3("小王",18,9000),"北京");
map.put(new Teacher3("小张",19,6000),"上海");
map.put(new Teacher3("小李",20,7000),"广州");
map.put(new Teacher3("小王",18,5000),"深圳");
System.out.println(map);
}
}
class Teacher3 {
private String name;
private int age;
private double salary;
public Teacher3(String name, int age, double salary) {
this.name = name;this.age = age;this.salary = salary;
}
public String getName() { return name; }
public int getAge() { return age; }
public double getSalary() { return salary; }
@Override
public String toString() {
return "Teacher3{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}' + "\n";
}
}
res
{Teacher3{name='小王', age=18, salary=5000.0} =深圳, Teacher3{name='小张', age=19, salary=6000.0} =上海, Teacher3{name='小李', age=20, salary=7000.0} =广州, Teacher3{name='小王', age=18, salary=9000.0} =北京}
MapTest6.java
import java.util.*;
public class MapTest6 {
public static void main(String[] args) {
//完成Map集合相关案例:投票统计程序
calc();
}
public static void calc(){
List<String> locations = new ArrayList<>();
String[] names = {"北京", "上海", "广州", "深圳"};
Random r = new Random();
for (int i = 0; i < 100; i++) {
int index = r.nextInt(names.length);
locations.add(names[index]);
}
Map<String, Integer> map = new HashMap<>();
for (String location : locations) {
if(map.containsKey(location)){
Integer count = map.get(location);
map.put(location, count + 1);
}else{
map.put(location, 1);
}
}
map.forEach((k,v)-> System.out.println(k + ":" + v));
}
}
res
上海:28 广州:27 深圳:20 北京:25
Stream
StreamDemo1.java
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class StreamDemo1 {
public static void main(String[] args) {
//目标:认识Stream流,掌握其基本使用步骤。体会它的优势和特点。
List<String> list = new ArrayList<>();
list.add("张无忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");list.add("张翠山");
//1、先用传统方案:找出姓张的人,名字为3个字的,存入到一个新集合中去。
List<String> newList = new ArrayList<>();
for(String name : list){
if(name.startsWith("张") && name.length() == 3){
newList.add(name);
}
}
System.out.println(newList);
System.out.println("--------------------");
//2、用Stream流实现
List<String> newList2 = list.stream().filter(name -> name.startsWith("张")).
filter(name -> name.length() == 3).collect(Collectors.toList());
System.out.println(newList2);
System.out.println("--------------------");
list.stream()
.filter(name -> name.startsWith("张"))
.filter(name -> name.length() == 3)
.forEach(name -> System.out.println(name));
}
}
res
[张无忌, 张三丰, 张翠山] -------------------- [张无忌, 张三丰, 张翠山] -------------------- 张无忌 张三丰 张翠山
StreamDemo2.java
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo2 {
public static void main(String[] args) {
//目标:获取Stream流的方式,
//1、获取集合的stream流:调用集合提供的stream()方法
Collection<String> list = new ArrayList<>();
Stream<String> s1 = list.stream();
//2、Map集合,怎么拿Stream流。
Map<String,Integer> map = new HashMap<>();
Stream<String> s2 = map.keySet().stream();//获取所有的键的stream流
Stream<Integer> s3 = map.values().stream();//获取所有的值的stream流
Stream<Map.Entry<String,Integer>> s4 = map.entrySet().stream();//获取所有的键值对的stream流
//3、数组,怎么拿Stream流。
String[] names = {"张三丰", "张无忌", "赵敏", "周芷若","张伟"};
Stream<String> s5 = Arrays.stream(names);
System.out.println(s5.count());//5
Stream<String> s6 = Stream.of("张三丰", "张无忌", "赵敏", "周芷若","张伟");
}
}
StreamDemo3.java
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class StreamDemo3 {
public static void main(String[] args) {
//目标:掌握Stream提供的常用的中间方法,对流上的数据进行处理(返回新流:支持链式编程)
List<String> list = new ArrayList<>();
list.add("张无忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");
list.add("张翠山");list.add("张良");list.add("王二麻子");list.add("谢广坤");list.add("冬雪莲");
//1.过滤方法
/*
list.stream().filter(name -> name.startsWith("张")).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
//list.stream().filter(name -> name.startsWith("张")).forEach(name -> System.out.println(name));
list.stream().filter(name -> name.startsWith("张")).forEach(System.out::println);
System.out.println("----------------------------------------------------------");
//2.排序方法
List<Double> list1 = new ArrayList<>();
list1.add(99.6);list1.add(35.8);list1.add(66.6);list1.add(77.7);list1.add(55.5);list1.add(88.8);list1.add(77.7);
list1.stream().sorted().forEach(num -> System.out.println(num));//默认升序
System.out.println("----------1----------");
list1.stream().sorted((o1, o2) -> Double.compare(o2, o1)).forEach(num -> System.out.println(num));//降序
System.out.println("----------2----------");
list1.stream().sorted((o1, o2) -> Double.compare(o2, o1)).limit(3).forEach(num -> System.out.println(num));//取前三个
System.out.println("----------3----------");
list1.stream().sorted((o1, o2) -> Double.compare(o2, o1)).skip(3).forEach(num -> System.out.println(num));//跳过前三个
System.out.println("----------4----------");
list1.stream().sorted((o1, o2) -> Double.compare(o2, o1)).distinct().forEach(num -> System.out.println(num));//去重
System.out.println("----------5----------");
//映射/加工方法:把流上原来的数据拿出来变成新数据又放到流上去,原本的数据不变
list1.stream().map(s -> "加10分后:" + (s + 10)).forEach(num -> System.out.println(num));
System.out.println("----------6----------");
//合并流
Stream<String> stream1 = list.stream();
Stream<Double> stream2 = list1.stream();
Stream<Object> stream3 = Stream.concat(stream1, stream2);
System.out.println(stream3.count());//17
}
}
res
张无忌 张强 张三丰 张翠山 张良 ---------------------------------------------------------- 35.8 55.5 66.6 77.7 77.7 88.8 99.6 ----------1---------- 99.6 88.8 77.7 77.7 66.6 55.5 35.8 ----------2---------- 99.6 88.8 77.7 ----------3---------- 77.7 66.6 55.5 35.8 ----------4---------- 99.6 88.8 77.7 66.6 55.5 35.8 ----------5---------- 加10分后:109.6 加10分后:45.8 加10分后:76.6 加10分后:87.7 加10分后:65.5 加10分后:98.8 加10分后:87.7 ----------6---------- 17
StreamDemo4.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamDemo4 {
public static void main(String[] args) {
//目标:掌握Stream流的统计,收集操作(终结方法)
List<Teacher> teachers = new ArrayList<>();
teachers.add(new Teacher("张三丰", 100, 10000));
teachers.add(new Teacher("张无忌", 20, 8000));
teachers.add(new Teacher("赵敏", 18, 6000));
teachers.add(new Teacher("周芷若", 17, 5000));
teachers.add(new Teacher("张强", 19, 4000));
teachers.add(new Teacher("张三", 20, 30000));
teachers.add(new Teacher("冬雪莲", 20, 8000));
teachers.add(new Teacher("梁志斌", 19, 4000));
teachers.stream().filter(t -> t.getSalary() > 7000).forEach(System.out::println);
System.out.println("--------------------1--------------------");
System.out.println(teachers.stream().filter(t -> t.getSalary() > 7000).count());
System.out.println("--------------------2--------------------");
//Optional<T> 是 Java 8 引入的容器类,用于优雅地处理可能为 null 的值
//防 NullPointerException:明确表示"值可能不存在",避免显式的 null 检查
//Optional<Teacher> max = teachers.stream().max((t1, t2) -> Double.compare(t1.getSalary(), t2.getSalary()));
Optional<Teacher> max = teachers.stream().max(Comparator.comparingDouble(Teacher::getSalary));
Teacher maxTeacher = max.get();
System.out.println(maxTeacher);
System.out.println("--------------------3--------------------");
//收集Stream流:就是把Stream流操作后的结果转回到集合或者数组中去返回
//Stream流:方便操作集合/数组的手段;集合/数组:才是开发中的目的
List<String> list = new ArrayList<>();
list.add("张无忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");
list.add("张翠山");list.add("张良");list.add("王二麻子");list.add("谢广坤");list.add("冬雪莲");
Stream<String> s1 = list.stream().filter(name -> name.startsWith("张"));
List<String> list1 = s1.collect(Collectors.toList());
System.out.println(list1);
System.out.println("--------------------4--------------------");
s1 = list.stream().filter(name -> name.startsWith("张"));
Set<String> set1 = s1.collect(Collectors.toSet());
System.out.println(set1);
System.out.println("--------------------5--------------------");
s1 = list.stream().filter(name -> name.startsWith("张"));
Object[] array1 = s1.toArray();
System.out.println(Arrays.toString(array1));
System.out.println("--------------------6--------------------");
//Stream<Teacher> s4 = teachers.stream().sorted((t1, t2) -> Double.compare(t1.getSalary(), t2.getSalary()));
Stream<Teacher> s4 = teachers.stream().sorted(Comparator.comparingDouble(Teacher::getSalary));
//收集到Map集合:键是老师名称,值是老师薪水
/*
Map<String, Double> map2 = s4.collect(Collectors.toMap(new Function<Teacher3, String>() {
@Override
public String apply(Teacher3 teacher) {
return teacher.getName();
}
}, new Function<Teacher3, Double>() {
@Override
public Double apply(Teacher3 teacher) {
return teacher.getSalary();
}
}));*/
Map<String, Double> map1 = s4.collect(Collectors.toMap(Teacher::getName, Teacher::getSalary));
System.out.println(map1);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Teacher implements Comparable<Teacher> {
private String name;
private int age;
private double salary;
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}' + "\n";
}
//t2.compareTo(t1)
//t2 == this 比较者
//t1 == o 被比较者
//如果返回值小于0,则认为t2小于t1,t2在t1之前。
//如果返回值大于0,则认为t2大于t1,t2在t1之后。
//如果返回值等于0,则认为t2等于t1,t2和t1在同一位置。
@Override
public int compareTo(Teacher o) {
//按年龄升序排序
if (this.getAge() > o.getAge()) return 1;
else if (this.getAge() < o.getAge()) return -1;
return 1;//保证年龄相同的值不会被剔除
}
}
res
Teacher{name='张三丰', age=100, salary=10000.0} Teacher{name='张无忌', age=20, salary=8000.0} Teacher{name='张三', age=20, salary=30000.0} Teacher{name='冬雪莲', age=20, salary=8000.0} --------------------1-------------------- 4 --------------------2-------------------- Teacher{name='张三', age=20, salary=30000.0} --------------------3-------------------- [张无忌, 张强, 张三丰, 张翠山, 张良] --------------------4-------------------- [张强, 张良, 张翠山, 张三丰, 张无忌] --------------------5-------------------- [张无忌, 张强, 张三丰, 张翠山, 张良] --------------------6-------------------- {张强=4000.0, 冬雪莲=8000.0, 梁志斌=4000.0, 张三=30000.0, 张三丰=10000.0, 周芷若=5000.0, 赵敏=6000.0, 张无忌=8000.0}
Collection工具 批量添加、打乱
CollectionDemo2.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionDemo2 {
public static void main(String[] args) {
//认识Collections工具类
List<String> list = List.of("hello", "world", "java");
List<String> list2 = new ArrayList<>();
/*这样加很慢
list2.add("hello");list2.add("world");list2.add("java");*/
//1.Collections的方法批量加
Collections.addAll(list2 , "hello","world","c","java","python","c++");
System.out.println(list2);//[hello, world, c, java, python, c++]
//2.打乱顺序
Collections.shuffle(list2);
System.out.println(list2);//[world, python, hello, c, java, c++]
}
}
Game.java 斗地主发牌模拟
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.*;
public class Game {
public static void main(String[] args) {
//目标:开发斗地主游戏。
//1、每张牌都是一个对象,定义牌类。
//2、游戏房间也是一个对象:定义房间类(54张牌,开始启动)
Room r = new Room();
r.start();
}
}
class Room{
//1、准备好54张牌,给房间使用:定义一个集合容器装54张牌。
private List<Card> allCards = new ArrayList<>();
{
//2、初始化54张牌,给房间使用:遍历四种花色,四种牌型。
String[] colors = {"♦","♣","♥","♠"};//花色
String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};//点数
for (String color : colors) {
for (String size : sizes) {
allCards.add(new Card(size,color));
}
}
//3、将大小王添加到牌集中。
/*allCards.add(new Card("小王",""));
allCards.add(new Card("大王",""));*/
Collections.addAll(allCards,new Card("小王",""),new Card("大王",""));
System.out.println(allCards);
}
public void start(){
//4、洗牌,打乱牌的顺序。
Collections.shuffle(allCards);
//5、发牌,给三个玩家,17张牌,3个玩家,17张牌,底牌3张。
Map<String, List<Card>> plays = new HashMap<>();
List<Card> cards1 = new ArrayList<>();
plays.put("player1",cards1);
List<Card> cards2 = new ArrayList<>();
plays.put("player2",cards2);
List<Card> cards3 = new ArrayList<>();
plays.put("player3",cards3);
List<Card> dipai = new ArrayList<>();
for (int i = 0; i < allCards.size(); i += 3) {
if(i >= allCards.size() - 3){
dipai.add(allCards.get(i));
dipai.add(allCards.get(i + 1));
dipai.add(allCards.get(i + 2));
}
cards1.add(allCards.get(i));
cards2.add(allCards.get(i + 1));
cards3.add(allCards.get(i + 2));
}
/*用List
//定义三个集合,分别存储三个玩家的牌。
List<Card> player1 = new ArrayList<>();
List<Card> player2 = new ArrayList<>();
List<Card> player3 = new ArrayList<>();
List<Card> dipai = new ArrayList<>();
//遍历牌集合,获取每一张牌。
for (int i = 0; i < allCards.size(); i++) {
Card card = allCards.get(i);
if(i >= allCards.size() - 3){
dipai.add(card);
}else if(i % 3 == 0){
player1.add(card);
}else if(i % 3 == 1){
player2.add(card);
}else if(i % 3 == 2){
player3.add(card);
}
}
System.out.println("底牌:" + dipai);
System.out.println("玩家1:" + player1);
System.out.println("玩家2:" + player2);
System.out.println("玩家3:" + player3);*/
//6、排序,按照牌的大小进行排序。
for(List<Card> cards : plays.values()){
//cards.sort((o1, o2) -> o1.compareTo(o2));
cards.sort(Card::compareTo);
}
dipai.sort((o1, o2) -> o1.compareTo(o2));
//7、看牌,看牌 everyone: everyone.forEach(card -> System.out.println(card));
for (Map.Entry<String, List<Card>> entry : plays.entrySet()) {
String name = entry.getKey();
List<Card> cards = entry.getValue();
System.out.println(name + ":" + cards);
}
System.out.println("底牌:" + dipai);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Card{
private String size;
private String color;
// 将点数映射为数值
private int getSizeValue(){
switch(size){
case "J": return 11;
case "Q": return 12;
case "K": return 13;
case "A": return 14;
case "2": return 15;
case "小王": return 16;
case "大王": return 17;
default: return Integer.parseInt(size);//其他点数直接转换为整数
}
}
public int compareTo(Card o) {
// 先比较点数
int sizeCompare = Integer.compare(this.getSizeValue(), o.getSizeValue());
if (sizeCompare != 0) { return sizeCompare; }
// 点数相同,比较花色
return this.color.compareTo(o.color);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return Objects.equals(size, card.size) && Objects.equals(color, card.color);
}
@Override
public String toString() { return size + color; }
}
res
[3♦, 4♦, 5♦, 6♦, 7♦, 8♦, 9♦, 10♦, J♦, Q♦, K♦, A♦, 2♦, 3♣, 4♣, 5♣, 6♣, 7♣, 8♣, 9♣, 10♣, J♣, Q♣, K♣, A♣, 2♣, 3♥, 4♥, 5♥, 6♥, 7♥, 8♥, 9♥, 10♥, J♥, Q♥, K♥, A♥, 2♥, 3♠, 4♠, 5♠, 6♠, 7♠, 8♠, 9♠, 10♠, J♠, Q♠, K♠, A♠, 2♠, 小王, 大王] player1:[3♥, 4♣, 5♣, 6♣, 6♥, 7♥, 7♦, 8♦, 9♣, 9♥, 9♦, J♠, J♣, Q♣, K♦, A♣, 2♠, 2♦] player2:[3♠, 4♦, 5♠, 5♥, 6♠, 6♦, 7♠, 7♣, 8♠, 8♥, 10♣, 10♦, J♦, K♠, K♣, A♠, 2♥, 小王] player3:[3♣, 3♦, 4♠, 4♥, 5♦, 8♣, 9♠, 10♠, 10♥, J♥, Q♠, Q♥, Q♦, K♥, A♥, A♦, 2♣, 大王] 底牌:[4♣, 5♦, 8♥]
Param可变参数
ParamDemo1.java
import java.util.Arrays;
public class ParamDemo1 {
public static void main(String[] args) {
//目标:认识可变参数
//方法中可变参数 就是一种特殊形参,定义在方法、构造器的形参列表里,格式是:数据类型...参数名称;
//特点:可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它。好处:常常用来灵活的接收数据
sum();
sum(10);
sum(10,20,30,40);
sum(new int[]{10,20,30,40});
}
//注意事项:可变参数在形参列表中只能有一个,可变参数必须放在形参列表的最后面
public static void sum(int... nums) {
//可变参数对内实际上就是一个数组。nums就是数组.
System.out.println(nums.length);
System.out.println(Arrays.toString(nums));
System.out.println("------------------------");
}
}
res
0 [] ------------------------ 1 [10] ------------------------ 4 [10, 20, 30, 40] ------------------------ 4 [10, 20, 30, 40] ------------------------