一、static、final、权限关键字,代码块,接口,枚举

1 关键字
2 代码块
3 接口
4 枚举
  • idea快捷键

  • shift + enter 换行
    ctrl + Alt + shift + U 查看类、接口之间的继承关系
    

1 Java中的关键字

1.1 static关键字

  • static关键字 :
    • 静态的意思 , 可以修饰变量 , 也可以修饰方法 , 被static修饰的成员 , 我们叫做静态成员
  • static特点 :
    • 静态成员被所类的所有对象共享
    • 随着类的加载而加载 , 优先于对象存在
    • 可以通过对象调用 , 也可以通过类名调用 , 建议使用类名
  • public class Student {String name;int age;static String school;public void show() {System.out.println(name + "---" + age + "---" + school);}
    }
    /*static关键字的特点 :1 静态成员被该类的所有对象的进行共享2 静态成员可以通过类名调用 , 也可以通过对象进行调用 , 推荐使用类名3 静态成员随着类的加载而加载 , 优先于对象存在*/
    public class StudentTest {public static void main(String[] args) {Student.school = "传智专修学院";Student s = new Student();s.name = "张三";s.age = 23;s.show();Student s2 = new Student();s2.show();}
    }
    
  • static内存图解

  • static关键字的注意事项
    • 静态方法中只能调用静态成员
    • 非静态方法中可以调用任何成员
    • 静态方法中不能存在this关键字

1.2 final关键字

  • final关键字 : 翻译中文代表最终的意思 , 是java的一个关键字 也是一个修饰符 , 可以修饰类 , 可以修饰方法 , 也可以修饰变量

  • final关键字修饰的特点

    • final修饰的类 : 不能被继承 , 没有子类(太监类)
    • fina修饰的方法 : 不能被重写
    • final修饰的变量
      • 基本数据类型 : 值不能改变
      • 引用数据类型 : 地址不可发生改变 , 对象的属性可改变
      • 注意 :
        • 被final修饰的变量 , 我们叫做自定义常量 , 命名规范 : 每个字母需要大写 , 多个单词之间用下划线分割
        • final修饰成员变量需要注意初始化时机的问题 , 1) 直接赋值 , 2) 在构造方法执行完毕前赋值
  • 
    /*final的特点final修饰的类 , 不能被继承, 也就是没有子类final修饰的方法 , 不能被重写final修饰的变量基本数据类型 : 值不可以发生改变引用数据类型 : 地址不可发生改变 , 对象的内容可以发生改变注意 :1 被final修饰的变量 , 我们叫做自定义常量 , 命名规范 : 每个字母需要大写 , 多个单词之间用下划线分割2 final修饰成员变量需要注意初始化时机的问题1) 直接赋值2) 在构造方法执行完毕前赋值*/
    public class FinalDemo1 {public static void main(String[] args) {// final修饰的基本数据类型变量 , 值不能被修改
    //        final int num = 10;
    //        num = 20;
    //        System.out.println(num);final int[] arr = {1, 2, 3, 4, 5};// final修饰的引用数据类型 , 地址不可改发生改变// arr = new int[3];// final修饰的引用数据类型 , 对象中的内容可以发生改变arr[0] = 100;}
    }// final修饰的类 , 不能被继承, 也就是没有子类
    //final class Person {//
    //}class Person {// final修饰的方法 , 不能被重写public final void eat() {}
    }class Student extends Person {// final修饰成员变量需要注意初始化时机的问题// 要么直接赋值 , 要么在构造方法执行完毕前赋值// final int num = 10;final int num;public Student() {num = 100;}//    @Override
    //    public void eat() {//        super.eat();
    //    }
    }

1.3 Java中的权限修饰符

  • public – protected – 默认的 – private


/*public -- protected -- 默认的 -- private*/
public class Fu {public void method1() {}protected void method2() {}void method3() {}private void method4() {}// 同一个包中同一个类public void show(){method1();method2();method3();method4();}}
===================================================package com.itheima.permissions_demo1;public class Test {// 同一个包中 , 无关类public void show(){Fu f = new Fu();f.method1();f.method2();f.method3();// f.method4();}
}
====================================================
package com.itheima.permissions_demo1;public class Zi extends Fu {// 用一个包中 , 有子类父关系public void show(){method1();method2();method3();// method4();}
}
package com.itheima.permissions_demo2;import com.itheima.permissions_demo1.Fu;public class Test {// 不同包中 , 无关类public void show(){Fu f = new Fu();f.method1();// f.method2();// f.method3();// f.method4();}
}======================================package com.itheima.permissions_demo2;import com.itheima.permissions_demo1.Fu;public class Zi extends Fu {// 不同包中 , 有子类父关系public void show(){method1();method2();// method3();// method4();}
}

2 代码块

2.1 构造代码块

  • 构造方法块 : 用一对大括号表示, 定义在类中方法外
  • 执行时机 : 每次构造方法执行前, 都会执行构造代码块
  • 作用 : 抽取构造方法中共性内容
package com.itheima.code_block;
/*构造代码块*/
public class Student {final int NUM;{NUM = 10;System.out.println("构造代码块...");}public Student() {System.out.println("空参构造...");}public Student(int a) {System.out.println("有参构造...");}
}class StudentTest {public static void main(String[] args) {Student s = new Student();Student s2 = new Student(10);}
}

2.2 静态代码块

  • 静态代码块 : 在一对大括号前加上static关键字 , 定义在类中方法外

  • 执行时机 : 随着类的加载而加载 , 只加载一次

  • 作用 : 一般用于给静态成员初始化

    package com.itheima.code_block.static_demo;
    /*静态代码块 :1 定义的位置 : 在一对大括号前加上static , 定义在类中方法外2 执行时机 ; 随着类的加载而执行, 只加载一次3 可以给类中的静态成员进行初始化数据*/
    public class Test {public static void main(String[] args) {new Student();new Student(10);}
    }
    

class Student {
static {
System.out.println(“静态代码块”);
}

public Student() {System.out.println("空参构造");
}public Student(int a) {System.out.println("有参构造");
}

}

2.3 局部代码块

  • 成员代码块 : 用一对大括号表 , 可以定义在任何的局部位置 , 方法中居多
  • 执行时机 : 正常执行(从上往下依次执行)
  • 控制变量的局部变量的声明周期
package com.itheima.code_block.local_demo;
/*局部代码块 :1 位置 : 可以定义任何的局部的位置 , 方法中居多2 执行时机 : 正常执行(从上往下依次执行)3 作用 : 控制变量的生命周期 , 变量在使用完毕, 及时释放内存*/
public class Test {public static void main(String[] args) {int num1 = 10;System.out.println(num1);// 局部代码块{int num2 = 20;System.out.println(num1);System.out.println(num2);}System.out.println(num1);//        System.out.println(num2);// 作用域不够 , 报错}
}

3 接口

3.1 接口的介绍

  • 接口 : 如果一个类中都是抽象方法 , 那么这个类应该是定义规则的类 , 我们应该把此类定义成接口,接口是一种引用数据类型
  • 作用 :
    • 用于定义规则
    • 程序的扩展性

3.2 接口的定义和特点

  • 定义接口的关键字使用interface

    • public interface 接口名{ … }
  • 类与接口之间的关系是实现关系 , 用关键字implements进行连接
    • public class 类名 implements 接口名 { … }
  • 接口不能实例化
  • 接口的子类我们叫做实现类
    • 要么重写接口中所有的抽象方法
    • 要么实现类是一个抽象类
  • 注意 : 类与接口的关系是实现关系 , 一个类可以实现多个接口,调用逗号分隔 , 还可以继承一个类的同时 , 实现多个接口
package com.itheima.interface_demo;public interface Inter {public abstract void show();public abstract void method();
}interface Inter2 {}
package com.itheima.interface_demo;public class InterImpl extends Object implements Inter ,Inter2{@Overridepublic void show() {}@Overridepublic void method() {}
}
package com.itheima.interface_demo;/*1 定义接口的关键字使用interfacepublic interface 接口名{ ... }2 类与接口的关系是实现关系 , 使用implements进行连接public class 类名 implements 接口名{ ... }3 接口不能实例化(不能创建对象)4 接口的子类,我们叫做实现类要么重写接口中所有的抽象方法要么这个实现类是一个抽象类注意 : 类与接口的关系是实现关系 , 一个类可以实现多个接口还可以继承一个类的同时 , 实现多个接口*/
public class InterfaceDemo1 {public static void main(String[] args) {// 接口不能实例化(不能创建对象)// Inter inter = new Inter();}
}

3.3 接口的成员特点

  • 成员变量 : 都是常量 , 默认修饰符 public static final
  • 构造方法 : 没有构造方法
  • 成员方法 : 只能是抽象方法 , 默认修饰符public abstract
    • 关于JDK8和JDK9版本对接口增加了一些方法新特性
package com.itheima.interface_demo;public interface Inter {// 是一个常量 , 默认修饰符 public static finalpublic static final int num = 10;// 不存在构造方法// public Inter(){}public abstract void show();public abstract void method();
}interface Inter2 {}
public class InterfaceDemo1 {public static void main(String[] args) {// 接口不能实例化(不能创建对象)// Inter inter = new Inter();// 成员变量被static修饰System.out.println(Inter.num);// 是一个常量 , 只能赋值一次// Inter.num = 20;}
}

3.4 接口的案例

package com.itheima.interface_demo.interface_test;public interface player {public abstract void play();public abstract void pause();public abstract void stop();
}
package com.itheima.interface_demo.interface_test;public class MP3 implements player {@Overridepublic void play() {System.out.println("MP3开始播放音乐");}@Overridepublic void pause() {System.out.println("MP3开始暂停");}@Overridepublic void stop() {System.out.println("MP3开始关闭音乐");}
}
package com.itheima.interface_demo.interface_test;public class MP4 implements player {@Overridepublic void play() {System.out.println("MP4播放音乐");}@Overridepublic void pause() {System.out.println("MP4暂停音乐");}@Overridepublic void stop() {System.out.println("MP4关闭音乐");}
}
package com.itheima.interface_demo.interface_test;
/*需求 :1  创建一个播放接口 player2  定义三个抽象方法 , 播放(play),暂停(pause),停止(stop)3  定义MP3类,MAP4类,手机类,实现接口,重写抽象方法*/
public class PlayerTest {public static void main(String[] args) {MP3 mp3 = new MP3();mp3.play();mp3.pause();mp3.stop();System.out.println("=============");MP4 mp4 = new MP4();mp4.play();mp4.pause();mp4.stop();}
}

3.5 接口中成员方法的特点

  • DK8版本之前 : 只能是抽象方法
  • JDK8版本 :
    • 默认方法

      • JDK8可以在接口中定义非抽象方法(带有方法体的方法) , 需要使用default进行修饰 , 其实就是默认方法
      • 作用 : 解决接口升级的问题
      • 格式 : public default 返回值类型 方法名(参数) { … }
      • 注意事项 :
        • 默认方法不是抽象方法 , 可以继承 , 也可以重写 , 重写需要去掉default关键字
        • public 可以省略 , default不能省略
        • 如果实现类实现了多个接口 , 有相同的方法声明 , 那么实现类必须重写该方法
    • 静态方法
      • JDK8可以在接口中定义静态方法 , 也是有方法体的方法
      • 作用 : 方便调用此功能
      • 格式 : public static 返回值类型 方法名(参数){ … }
      • 注意事项
        • 静态方法只能通过接口名调用 , 不能通过实现类名字和对象调用
        • public可以省略 , static不能省略
  • JDK9版本 :
    • 私有方法

      • JDK9中新增私有方法
      • 作用 : 抽取默认方法中共性内容
      • 格式 : private 返回值类型 方法名(参数){ … }
      • 注意 : 要想抽取静态方法中的共性内容 , 需要对私有方法加上关键字static

4 枚举

  • 枚举 : 当一个变量有几种固定可能的取值时,就可以将它定义为枚举类型
  • 作用 : 更贴切 , 加见名之意
  • 定义 : public enum 枚举名{ … }
  • 使用 : 通过枚举类型名直接引用枚举项即可,例如Sex.BOY、Sex.GIRL
    注意 : 每个枚举项都相当于枚举的对象
  • 枚举的本质 :
    • 枚举其实本质上是一个类,每一个枚举项是本枚举类类型的一个对象。我们可以使用JDK提供的反编译命令,将枚举的字节码进行反编译查看

      • 枚举本质上就是最终类
      • 枚举项,就是枚举类的对象,而且是静态的常量。
      • 有私有的构造方法
      • 静态代码块
      • 继承了lang包下的Enum
  • 组成部分 :
    • 构造器,成员方法,成员变量等 , 但是定义的成分一定要在枚举项之后,而且最后一个枚举项必须要有分号结束。

二、多态 ,内部类,常用API

  • 多态 ,内部类,常用API

  • 多态
  • 内部类
  • 常用API

1 多态

1.1 面向对象三大特征 ?

  • 封装 , 继承 , 多态

1.2 什么是多态 ?

  • 一个对象在不同时刻体现出来的不同形态

  • 举例 : 一只猫对象

    • 我们可以说猫就是猫 : Cat cat = new Cat();
    • 我们也可以说猫是动物 : Animal cat = new Cat();
    • 这里对象在不同时刻,体现出来的不同形态 , 我们就可以理解为多态

1.3 多态的前提

  • 有继承/实现关系
  • 有方法重写
  • 父类的引用指向子类的对象
package com.itheima.polymorphism_demo;
/*多态的三个前提条件1 需要有继承/实现关系2 需要有方法重写3 父类的引用指向子类的对象*/
public class AnimalTest {public static void main(String[] args) {// 3 父类的引用指向子类的对象// 多态形式对象Animal a = new Cat();}
}class Animal{public void eat(){System.out.println("吃东西");}
}class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼....");}
}

1.4 多态的成员访问特点

  • 构造方法 : 和继承一样 , 子类通过super()访问父类的构造方法
  • 成员变量 : 编译看左边(父类) , 执行看左边(父类)
  • 成员方法 : 编译看左边(父类) , 执行看右边(子类)
package com.itheima.polymorphism_demo;/*多态的成员访问特点 :1 构造方法 : 和继承一样 , 都是通过super()访问父类的构造方法2 成员变量 : 编译看左边(父类) , 执行看左边(父类)3 成员方法 : 编译看左边(父类) , 执行看右边(子类) , 注意 , 如果执行时1) 子类没有回动态去找父类中的方法2) 子类的特有方法无法进行调用(多态的缺点)*/
public class MemberTest {public static void main(String[] args) {// 父类的引用指向子类的对象Fu f = new Zi();// 多态对象调用成员变量System.out.println(f.num);// 多态对新乡调用调用成员方法f.show();// 多态对象不能调用子类特有的方法// f.show2();}
}class Fu {int num = 100;public void show() {System.out.println("父类的show方法");}
}class Zi extends Fu {int num = 10;public void show() {System.out.println("子类的show方法");}public void show2(){System.out.println("子类特有的方法");}
}

1.5 多态的优缺点

  • 优点 : 提高代码的扩展性
  • 缺点 : 不能调用子类特有的功能
package com.itheima.polymorphism_test;public abstract class Animal {private String breed;private String color;public Animal() {}public Animal(String breed, String color) {this.breed = breed;this.color = color;}public String getBreed() {return breed;}public void setBreed(String breed) {this.breed = breed;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public abstract void eat();
}
package com.itheima.polymorphism_test;public class Cat extends Animal {public Cat() {}public Cat(String breed, String color) {super(breed, color);}@Overridepublic void eat() {System.out.println("猫吃鱼...");}public void catchMouse() {System.out.println("抓老鼠...");}
}
package com.itheima.polymorphism_test;public class Dog extends Animal {public Dog() {}public Dog(String breed, String color) {super(breed, color);}@Overridepublic void eat() {System.out.println("狗吃骨头!");}public void lookDoor(){System.out.println("狗看门...");}
}
package com.itheima.polymorphism_test;public class Pig extends Animal {public Pig() {}public Pig(String breed, String color) {super(breed, color);}@Overridepublic void eat() {System.out.println("猪拱白菜...");}public void sleep() {System.out.println("一直再睡...");}
}
package com.itheima.polymorphism_test;/*如果方法的参数是一个类的话 , 那么调用此方法需要传入此类的对象 , 或者子类对象多态的好处 :提高代码的扩展性 , 灵活性多态的缺点:不能调用子类的特有功能*/
public class AnimalTest {public static void main(String[] args) {useAnimal(new Cat());System.out.println("---------");useAnimal(new Dog());System.out.println("---------");useAnimal(new Pig());}public static void useAnimal(Animal a){// Animal a = new Dog()a.eat();// 多态不能访问子类特有的功能// 如果解决 ?// 向下转型if(a instanceof Cat) {Cat cat = (Cat) a;cat.catchMouse();}if(a instanceof Dog) {Dog dog = (Dog) a;dog.lookDoor();}if(a instanceof Pig) {((Pig) a).sleep();}}//    // 定义一个使用猫类的方法
//    public static void useAnimal(Cat c) {// Cat c = new Cat();
//        c.eat();
//        c.catchMouse();
//    }
//
//    // 定义一个使用狗类的方法
//    public static void useAnimal(Dog d) {// Dog d = new Dog();
//        d.eat();
//        d.lookDoor();
//    }
//
//    // 定义一个使用猪类的方法
//    public static void useAnimal(Pig pig) {//        pig.eat();
//        pig.sleep();
//    }
}

1.6 多态的转型

  • 向上转型 : 把子类类型数据转成父类类型数据 Animal a = new Cat();
  • 向下转型 : 把父类类型数据转成子类类型数据 Cat cat = (Cat)a;

1.7 多态的转型注意

  • 如果被转的对象 , 对应的实际类型和目标类型不是同一种数据类型 , 那么转换时会出现ClassCastException异常

  • 异常代码如下
    public static void main(String[] args) {Animal a = new Cat();useAnimal(a);
    }
    public static void useAnimal(Animal a) {Dog d = (Dog) a;d.eat();
    }

1.8 解决转型安全隐患

  • 使用关键字 instanceof
  • 作用 : 判断一个对象是否属于一种引用数据类型
  • 格式 : 对象名 instanceof 引用数据类型
    • 通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果

2 内部类

2.1 内部类的分类

  • 什么是内部类 ?
    • 一个A类 中 定义一个B类 , 那么B类就属于A类的内部类 , A类就属于B类的外部类

  • 什么时候使用内部类 ?
    • 多个事物之间有包含关系, 可以使用内部类
  • 内部类分类 ?
    • 成员内部类
    • 局部内部类
    • 匿名内部类

2.2 成员内部类

  • 定义的位置 : 类中方法外

  • 创建成员内部类对象格式 : 外部类名.内部类名 对象名 = new 外部类名().new 内部类名(参数);

    package com.itheima.innerclass_demo.member_innerclass;// 外部类
    public class Person {// 成员内部类public class Heart {// 频率变量private int rate;// 跳动方法public void beats() {System.out.println("咚咚咚!");}}
    }class Test {public static void main(String[] args) {// 创建内部类对象Person.Heart heart = new Person().new Heart();// 调用内部类中的方法heart.beats();}
    }
    
  • 成员内部类访问外部类的成员
    • 在内部类中有代表外部类对象的格式 : 外部类名的.this , 私有的也可以访问
    • 外部类要想访问内部类成员 , 需要创建内部类对象
    package com.itheima.innerclass_demo.member_innerclass;public class Person {private String name = "张三";private int num = 10;// 成员内部类public class Heart {int num = 100;// 频率private int rate;// 跳动public void beats() {System.out.println("咚咚咚!");}// 调用外部类的成员public void show(){int num = 1000;System.out.println(Person.this.name);System.out.println(num);// 1000 就近原则System.out.println(this.num);// 100System.out.println(Person.this.num);// 10}}
    }class Test {public static void main(String[] args) {Person.Heart heart = new Person().new Heart();heart.beats();heart.show();}
    }
    

2.3 匿名内部类

  • 匿名内部类 : 没有名字的类 , 一次性产品
  • 使用场景 : 直接调用方法 , 作为方法的传参 , 返回值类型
  • 好处 : 简化代码 , 快速实现接口或者抽象的抽象方法
  • 格式 :
    • new 类名/接口名(){ 重写抽象方法 } 注意 : 此处创建的是子类对象!!!
  • 使用方式 :
    • 直接调用方法
    • 作为方法的参数传递
    • 作为方法的返回值类型
//接口
interface Flyable {void fly();
}
// 直接调用方法
Flyable f1 = new Flyable() {@Overridepublic void fly() {System.out.println("不知道什么在飞.....");}
};
f1.fly();
// 作为方法的参数传递
showFlyable(new Flyable() {@Overridepublic void fly() {System.out.println("不知道什么在飞3333");}}
);public static void showFlyable(Flyable flyable) {flyable.fly();
}
// 作为方法的返回值类型
public static Flyable getFlyable() {return new Flyable() {@Overridepublic void fly() {System.out.println("3333333333333");}};
}
package com.itheima.innerclass_demo.anonymous_innerclass;/*1 如果方法的参数是一个类的话 , 调用此方法需要传入此类的对象或者此类的子类对象2 如果方法的返回值类型是一个类的话 , 需要返回此类的对象 , 或者此类的子类对象3 如果方法的参数是一个接口的话 , 调用此方法需要传入此接口的实现类对象4 如果方法的返回值类型是一个接口的话 , 需要返回此接口的实现类对象匿名内部类 : 代表的就是子类对象!!!new 类名/接口名(){重写抽象类或者接口中的抽象方法};使用方向 :1 调用方法2 作为方法参数传递3 作为方法的返回值*/
public interface Swim {public abstract void swimming();
}class Test {public static void main(String[] args) {//        // 子类对象!!!//  1 调用方法
//       new Swim() {//            @Override
//            public void swimming() {//                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
//            }
//        }.swimming();//        //   2 作为方法参数传递
//        useSwim(new Swim() {//            @Override
//            public void swimming() {//                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
//            }
//        });//        // 3 作为方法的返回值
//        Swim s = getSwim();
//        s.swimming();}public static Swim getSwim() {return new Swim() {@Overridepublic void swimming() {System.out.println("匿名内部类 , 重写了接口中的抽象方法...");}};}/*Swim swim = new Swim() {@Overridepublic void swimming() {System.out.println("匿名内部类 , 重写了接口中的抽象方法...");}};*/public static void useSwim(Swim swim) {swim.swimming();}
}

3 API

3.1 Object类

  • 概述 : 类Object是类层次结构的根,每个类都把Object作为超类。 所有对象(包括数组)都实现了这个类的方法
  • 方法 : public String toString()
    • 如果一个类没有重写toString方法 , 那么打印此类的对象 , 打印的是此对象的地址值
    • 如果一个类重写了toString方法 , 那么打印此类的对象 , 打印的是此对象的属性值
    • 好处 : 把对象转成字符串 , 快速查看一个对象的属性值
    • 执行时机 : 打印对象时会默认调用toString方法
  • 方法 : public boolean equals()
    • 如果一个类没有重写equals方法 , 那么比较此类的对象 . 比较的是地址值
    • 如果一个类重写了equals方法 . 那么比较此类的对象 , 比较的是属性值是否相等
    • 好处 : 可以比较对象的内容

3.2 Objects类

  • Objects是JDK1.7新增的一个对象工具类,里面都是静态方法可以用来操作对象。比如对象的比较,计算对象的hash值,判断对手是否为空…比如里面的equals方法,可以避免空指针异常
public static boolean equals(Object a, Object b):判断两个对象是否相等public static boolean equals(Object a, Object b) {return (a == b) || (a != null && a.equals(b));
}
a.equals(b) :如果a是null值,肯定会空指针
Objects.equals(a,b);:如果a是null,不会导致空指针异常

3.2 Date类

package com.itheima.api_demo.date_demo;import java.util.Date;/*Date类 : 代表的是一个瞬间 , 精确到毫秒构造方法 :public Date() : 代表的是当前系统时间public Date(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值成员方法 :public void setTime(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值public long getTime() : 返回的是毫秒值 = Date代表的时间 - 1970/1/1 0:0:0*/
public class DateDemo {public static void main(String[] args) {//  public Date() : 代表的是当前系统时间
//        Date d = new Date();
//        System.out.println(d);//  public Date(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
//        Date d2 = new Date(1000L * 60 * 60 * 24); // 1970/1/1 0:0:0 + 一天的毫秒值
//        System.out.println(d2);Date d = new Date();// public void setTime(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值// d.setTime(1000L * 60 * 60 * 24);System.out.println(d);// public long getTime() : 返回的是毫秒值 = Date代表的时间 - 1970/1/1 0:0:0// System.out.println(d.getTime());}
}

3.3 DateFormat类

  • 概述 : 主要用于操作日期格式的一个类

  • 作用 :

    • 格式化 : Date --> String
    • 解析 : String --> Date
  • 构造方法 :

    • SimpleDateFormat(String pattern) 给定日期模板创建日期格式化对象

  • 成员方法 :

    • public String format ( Date d ):格式化,将日期对象格式化为字符串
    • public Date parse ( String s ):解析,将字符串解析为日期对象
package com.itheima.api_demo.dateformat_demo;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*SimpleDateFormat类 :"2021年04月03日 16:48:10"  ---> DateDate(Sat Apr 03 16:41:38 CST 2021) --> "2021年04月03日 16:48:10"作用 :格式化 : Date --> String解析   : String --> Date构造方法 :public SimpleDateFormat(String pattern) : pattern : 字符串类型的日期模板成员方法 ;public final String format(Date date) : 接收一个Date对象返回指定模式的字符串public Date parse(String source) : 接收一个字符串  , 返回一个Date对象1 获取当前的日期对象,使用格式:yyyy-MM-dd HH:mm:ss 来表示,例如:2020-10-31 17:00:00【格式化】2 将字符串的 2020年10月31日  17:00:00,转换为日期Date对象。【解析】*/
public class SimpleDateFormatDemo {public static void main(String[] args) throws ParseException {// 解析   : String --> DateString strDate = "2020年10月31日 17:00:00";// 注意 : 解析时 , SimpleDateFormat的参数(日期模板) , 必须和要解析字符串的模式匹配SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//  public Date parse(String source) : 接收一个字符串  , 返回一个Date对象Date date = sdf.parse(strDate);System.out.println(date); // Sat Oct 31 17:00:00 CST 2020}private static void method() {// 格式化 : Date --> String// 获取当前系统时间Date date = new Date();// System.out.println(date);// Sat Apr 03 16:53:35 CST 2021// public SimpleDateFormat(String pattern) : pattern : 字符串类型的日期模板SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// public final String format(Date date) : 接收一个Date对象返回指定模式的字符串String strDate = sdf.format(date);System.out.println(strDate);}
}

3.4 Calendar类

  • 概述 :
    • java.util.Calendar类表示日历,内含有各种时间信息,以及获取,计算时间的方法。
    • Calendar本身是一个抽象类,可以通过Calendar提供的静态方法getInstance日历子类对象
  • Calendar常用方法 :
    方法名 说明
    public static Calendar getInstance() 获取一个它的子类GregorianCalendar对象。
    public int get(int field) 获取指定日历字段的时间值。
    public void set(int field,int value) 设置指定字段的时间值
    public void add(int field,int amount) 为某个字段增加/减少指定的值
  • get,set,add方法参数中都有一个整数类型的参数field,field用来区分当前要获取或者操作的日期时间数据的。field数据的值使用Calender中定义的整数常量来表示

    • Calendar.YEAR : 年
    • Calendar.MONTH :月
    • Calendar.DAY_OF_MONTH:月中的周
    • Calendar.HOUR:小时
    • Calendar.MINUTE:分钟,
    • Calendar.SECOND:秒
    • Calendar.DAY_OF_WEEK:星期
  • 星期对应的关系

    ​ 字段时间值 : 1 2 3 … 7
    ​ 真正的时间 : SUNDAY MONDAY TUESDAY … SATURDAY

  • 月份对应的关系

    ​ 字段时间值 : 0 1 … 11
    ​ 正真的时间 : JANUARY FEBRUARY … DECEMBER

package com.itheima.api_demo.calendar_demo;
/*月份对应的关系字段时间值     :       0           1           ....        11正真的时间     :     JANUARY     FEBRUARY      ....      DECEMBER*/
import java.util.Calendar;
/*成员方法 :public int get(int field)   获取指定日历字段的时间值。public void set(int field,int value)   设置指定字段的时间值public void add(int field,int amount) 为某个字段增加/减少指定的值*/
public class CalendarDemo {public static void main(String[] args) {// 获取Calendar对象 , rightNow对象Calendar rightNow = Calendar.getInstance();// public void set(int field , int value)    设置指定字段的时间值// rightNow.set(Calendar.YEAR , 2024);// rightNow.set(Calendar.MONTH , 5);// rightNow.set(Calendar.DAY_OF_MONTH, 10);// public void add(int field,int amount) 为某个字段增加/减少指定的值// rightNow.add(Calendar.DAY_OF_MONTH , -3);//  public int get(int field)  : 获取指定日历字段的时间值。int year = rightNow.get(Calendar.YEAR);int month = rightNow.get(Calendar.MONTH);int day = rightNow.get(Calendar.DAY_OF_MONTH);System.out.println(year); // 2021System.out.println(month);// 3System.out.println(day);  // 3}
}
package com.itheima.api_demo.calendar_demo;import java.util.Calendar;/*1 写代码使用get方法,将年,月,日,时,分,秒,周获取出来特别注意获取月份,和星期有以下特点:直接获取的月份数据是从0开始的, 0表示1月,.....11表示12月周的获取,从周日开始计算,1就是周日,2就是周一 ......7就是周六星期对应的关系字段时间值  :   1           2            3          ...        7真正的时间  : SUNDAY        MONDAY      TUESDAY     ...        SATURDAY月份对应的关系字段时间值     :       0           1           ....        11正真的时间     :     JANUARY     FEBRUARY      ....      DECEMBER*/
public class Test1 {public static void main(String[] args) {// 拿到当前时间Calendar now = Calendar.getInstance();System.out.println(now.get(Calendar.YEAR));System.out.println(now.get(Calendar.MONTH));System.out.println(now.get(Calendar.DAY_OF_MONTH));System.out.println(now.get(Calendar.HOUR));System.out.println(now.get(Calendar.MINUTE));System.out.println(now.get(Calendar.SECOND));int week = now.get(Calendar.DAY_OF_WEEK);// 7System.out.println(getWeek(week));// 字段值}public static String getWeek(int field){String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};return str[field];}
}
package com.itheima.api_demo.calendar_demo;import java.util.Calendar;/*2 写代码实现,获取2022年10月1日是星期几?参考思路:直接获取日历对象,得到的是当前系统的日历时间信息。获取日历对象后,要重新设置日期再获取星期数据*/
public class Test2 {public static void main(String[] args) {Calendar cal = Calendar.getInstance();cal.set(Calendar.YEAR, 2022);cal.set(Calendar.MONTH, 9);cal.set(Calendar.DAY_OF_MONTH, 1);int week = cal.get(Calendar.DAY_OF_WEEK);System.out.println(getWeek(week));// 字段值}public static String getWeek(int field){String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};return str[field];}
}
package com.itheima.api_demo.calendar_demo;import java.util.Calendar;/*3 计算10000天之后的年月日参考思路:先获取当前日历对象再调用add方法,指定DATE或者DAY_OF_MONTH,添加10000天再获取日历的年,月,日*/
public class Test3 {public static void main(String[] args) {Calendar cal = Calendar.getInstance();cal.add(Calendar.DAY_OF_MONTH, 10000);System.out.println(cal.get(Calendar.YEAR));System.out.println(cal.get(Calendar.MONTH));System.out.println(cal.get(Calendar.DAY_OF_MONTH));}
}

3.5 Math类

  • 概述 : Math包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。所提供的都是静态方法,可以直接调用

  • 常用方法 :

    public static int abs(int a) 获取参数a的绝对值:
    public static double ceil(double a) 向上取整
    public static double floor(double a) 向下取整
    public static double pow(double a, double b) 获取a的b次幂
    public static long round(double a) 四舍五入取整

3.6 System类

  • System类包含几个有用的类字段和方法。 它不能被实例化

  • 常用方法 :

    方法名 说明
    public static void exit(int status) 终止当前运行的 Java 虚拟机,非零表示异常终止
    public static long currentTimeMillis() 返回当前时间(以毫秒为单位)

三、常用API,正则表达式,Collection集合

学习内容

  • BigInteger类
  • BigDecimal类
  • Arrays类
  • 包装类
  • String类的常用方法
  • 正则表达式
  • Collection集合

1 BigInteger类

1.1 概述

  • 概述 : java.math.BigInteger类是一个引用数据类型 , 可以用于计算一些大的整数 , 当超出基本数据类型数据范围的整数运算时就可以使用BigInteger了。

1.2 构造方法

  • 构造方法 : 可以将整数的字符串 . 转成BigInteger类型的对象

1.3 成员方法

  • 方法声明 描述
    public BigInteger add (BigInteger value) 超大整数加法运算
    public BigInteger subtract (BigInteger value) 超大整数减法运算
    public BigInteger multiply (BigInteger value) 超大整数乘法运算
    public BigInteger divide (BigInteger value) 超大整数除法运算,除不尽取整数部分
package com.itheima.api_demo.biginteger_demo;import java.math.BigInteger;/*构造方法 :BigInteger(String value)    可以将整数的字符串,转换为BigInteger对象成员方法 :public BigInteger add (BigInteger value)      超大整数加法运算public BigInteger subtract (BigInteger value)   超大整数减法运算public BigInteger multiply (BigInteger value)   超大整数乘法运算public BigInteger divide (BigInteger value) 超大整数除法运算,除不尽取整数部分*/
public class BigIntegerDemo {public static void main(String[] args) {// 获取大整数对象BigInteger bigInteger1 = new BigInteger("2147483648");// 获取大整数对象BigInteger bigInteger2 = new BigInteger("2");// public BigInteger add (BigInteger value)       超大整数加法运算BigInteger add = bigInteger1.add(bigInteger2);System.out.println(add);System.out.println("=============");// public BigInteger subtract (BigInteger value)  超大整数减法运算BigInteger subtract = bigInteger1.subtract(bigInteger2);System.out.println(subtract);System.out.println("=============");// public BigInteger multiply (BigInteger value)   超大整数乘法运算BigInteger multiply = bigInteger1.multiply(bigInteger2);System.out.println(multiply);System.out.println("=============");// public BigInteger divide (BigInteger value) 超大整数除法运算,除不尽取整数部分BigInteger divide = bigInteger1.divide(bigInteger2);System.out.println(divide);}
}

2 BigDecimal类

2.1 概述

  • 概述 : java.math.BigDecimal可以对大浮点数进行运算,保证运算的准确性。float,double 他们在存储及运算的时候,会导致数据精度的丢失。如果要保证运算的准确性,就需要使用BigDecimal。

2.2 构造方法

  • 构造方法 :

    • public BigDecimal(String val) : 将 BigDecimal 的字符串表示形式转换为 BigDecimal

2.3 成员方法

  • 成员方法 :

    • 方法声明 描述
      public BigDecimal add(BigDecimal value) 加法运算
      public BigDecimal subtract(BigDecimal value) 减法运算
      public BigDecimal multiply(BigDecimal value) 乘法运算
      public BigDecimal divide(BigDecimal value) 除法运算(除不尽会有异常)
      public BigDecimal divide(BigDecimal divisor, int roundingMode) 除法运算(除不尽,使用该方法)参数说明:scale 精确位数,roundingMode取舍模式 BigDecimal.ROUND_HALF_UP 四舍五入 BigDecimal.ROUND_FLOOR 去尾法 BigDecimal.ROUND_UP 进一法
package com.itheima.api_demo.bigdecimal_demo;import java.math.BigDecimal;/*构造方法 :public BigDecimal(String val)   将 BigDecimal 的字符串表示形式转换为 BigDecimal成员方法 :public BigDecimal add(BigDecimal value)    加法运算public BigDecimal subtract(BigDecimal value)    减法运算public BigDecimal multiply(BigDecimal value)    乘法运算public BigDecimal divide(BigDecimal value)  除法运算(除不尽会有异常)public BigDecimal divide(BigDecimal value, int scale, RoundingMode roundingMode)   除法运算(除不尽,使用该方法)参数说明:scale 精确位数,roundingMode取舍模式BigDecimal.ROUND_HALF_UP 四舍五入BigDecimal.ROUND_FLOOR 去尾法BigDecimal.ROUND_UP  进一法*/
public class BigDecimalDemo {public static void main(String[] args) {BigDecimal bigDecimal1 = new BigDecimal("0.1");BigDecimal bigDecimal2 = new BigDecimal("0.2");// public BigDecimal add(BigDecimal value) 加法运算BigDecimal add = bigDecimal1.add(bigDecimal2);System.out.println(add);System.out.println("=================");// public BigDecimal subtract(BigDecimal value)   减法运算BigDecimal subtract = bigDecimal1.subtract(bigDecimal2);System.out.println(subtract);System.out.println("=================");// public BigDecimal multiply(BigDecimal value)    乘法运算BigDecimal multiply = bigDecimal1.multiply(bigDecimal2);System.out.println(multiply);System.out.println("=================");// public BigDecimal divide(BigDecimal value)  除法运算(除不尽会有异常)// BigDecimal divide = bigDecimal1.divide(bigDecimal2);// System.out.println(divide);/*public BigDecimal divide(BigDecimal divisor, int roundingMode) 除法运算(除不尽,使用该方法)参数说明:scale 精确位数,roundingMode : 取舍模式BigDecimal.ROUND_HALF_UP 四舍五入BigDecimal.ROUND_FLOOR 去尾法BigDecimal.ROUND_UP  进一法*/// BigDecimal divide = bigDecimal1.divide(bigDecimal2, 3, BigDecimal.ROUND_HALF_UP);// BigDecimal divide = bigDecimal1.divide(bigDecimal2, 3, BigDecimal.ROUND_FLOOR);// BigDecimal divide = bigDecimal1.divide(bigDecimal2, 3, BigDecimal.ROUND_UP);// System.out.println(divide);}
}

3 Arrays类

3.1 概述

  • 概述 : java.util.Arrays是数组的工具类,里面有很多静态的方法用来对数组进行操作(如排序和搜索),还包含一个静态工厂,可以将数组转换为List集合(后面会讲到集合知识

3.2 构造方法

  • 构造方法 : private Arrays(){}

  • public static void sort(int[] a) 按照数字顺序排列指定的数组
    public static String toString(int[] a) 返回指定数组的内容的字符串表示形式
package com.itheima.api_demo.arrays_demo;import java.util.Arrays;
import java.util.Random;/*1 随机生成10个[0,100]之间的整数,放到整数数组中,按照从小到大的顺序排序并打印元素内容。*/
public class ArraysDemo {public static void main(String[] args) {// 创建数组int[] arr = new int[10];// 创建随机数对象Random r = new Random();// 采用随机数给数组的每一个元素赋值for (int i = 0; i < arr.length; i++) {arr[i] = r.nextInt(101);}// 对数组进行排序Arrays.sort(arr);// 把数组转成指定格式的字符串System.out.println(Arrays.toString(arr));}
}

4 包装类

4.1 概述

  • 概述 :
    • Java中基本数据类型对应的引用数据类型

4.2 包装类的作用

  • 包装类的作用 :
    • 基本数据类型 , 没有变量 , 没有方法 , 包装类就是让基本数据类型拥有变量和属性 , 实现对象化交互
    • 基本数据类型和字符串之间的转换

4.3 基本数据类型和包装类对应

  • 基本数据类型和包装类的对应关系
    基本数据类型 包装类型
    byte Byte
    short Short
    int Integer
    long Long
    float Float
    double Double
    char Character
    boolean Boolean

4.4 自动装箱和自动拆箱

  • 自动转型和自动拆箱

    • 自动装箱和拆箱是JDK1.5开始的
    • 自动装箱 : 基本数据类型自动转成对应的包装类类型
    • 自动拆箱 : 包装类类型自动转成对应的基本数据类型
    Integer i1 = 10;
    int i2 = i1;
    

4.5 基本数据类型和字符串之间的转换

  • 使用包装类, 对基本数据类型和字符串之间的转换

    • 在开发过程中数据在不同平台之间传输时都以字符串形式存在的,有些数据表示的是数值含义,如果要用于计算我们就需要将其转换基本数据类型.

    • 基本数据类型–> String

      • 直接在数值后加一个空字符串
      • 通过String类静态方法valueOf()
    • String --> 基本数据类型

      • public static byte parseByte(String s):将字符串参数转换为对应的byte基本类型。
        public static short parseShort(String s):将字符串参数转换为对应的short基本类型。
        public static int parseInt(String s):将字符串参数转换为对应的int基本类型。
        public static long parseLong(String s):将字符串参数转换为对应的long基本类型。
        public static float parseFloat(String s):将字符串参数转换为对应的float基本类型。
        public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。
        public static boolean parseBoolean(String s):将字符串参数转换为对应的boolean基本类型。
  • 注意事项 :

    • 包装类对象的初始值为null(是一个对象)

    • Java中除了float和double的其他基本数据类型,都有常量池

      • 整数类型:[-128,127]值在常量池
      • 字符类型:[0,127]对应的字符在常量池
      • 布尔类型:true,false在常量池
    • 在常量池中的数据 , 会进行共享使用 , 不在常量池中的数据会创建一个新的对象

5 String类的常用方法

5.1 常用方法

package com.itheima.api_demo.string_demo;/*已知字符串,完成需求String str = "I Love Java, I Love Heima";判断是否存在  “Java”判断是否以Heima字符串结尾判断是否以Java开头判断 Java在字符串中的第一次出现位置判断  itcast 所在的位置*/
public class Test {public static void main(String[] args) {String str = "I Love Java, I Love Heima";// 判断是否存在  “Java”System.out.println(str.contains("Java"));// true// 判断是否以Heima字符串结尾System.out.println(str.endsWith("Heima"));// true// 判断是否以Java开头System.out.println(str.startsWith("Java"));// false// 判断 Java在字符串中的第一次出现位置System.out.println(str.indexOf("Java"));// 7// 判断  itcast 所在的位置System.out.println(str.indexOf("itcast"));// -1}
}
package com.itheima.api_demo.string_demo;/*已知字符串,完成右侧需求String str = "I Love Java, I Love Heima";需求:1.将所有 Love 替换为 Like ,打印替换后的新字符串2.截取字符串 "I Love Heima"3.截取字符串 "Java"*/
public class Test2 {public static void main(String[] args) {String str = "I Love Java, I Love Heima";// 1.将所有 Love 替换为 Like ,打印替换后的新字符串System.out.println(str.replace("Love", "Like"));// 2.截取字符串 "I Love Heima"System.out.println(str.substring(13));// 3.截取字符串 "Java"System.out.println(str.substring(7 , 11));}
}
package com.itheima.api_demo.string_demo;/*已知字符串,完成右侧需求String str = "I Love Java, I Love Heima";需求:1 计算字符 a 出现的次数(要求使用toCharArray)2 计算字符 a 出现的次数(要求使用charAt)3 将字符串中所有英文字母变成小写4 将字符串中所有英文字母变成大写*/
public class Test3 {public static void main(String[] args) {String str = "I Love Java, I Love Heima";//        1 计算字符 a 出现的次数(要求使用toCharArray)int count1 = 0;char[] chars = str.toCharArray();for (int i = 0; i < chars.length; i++) {if (chars[i] == 'a') {count1++;}}System.out.println("字符a出现了" + count1 + "次");//        2 计算字符 a 出现的次数(要求使用charAt)int count2 = 0;for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);if(ch == 'a'){count2++;}}System.out.println("字符a出现了" + count2 + "次");//        3 将字符串中所有英文字母变成小写String s1 = str.toLowerCase();System.out.println(s1);//        4 将字符串中所有英文字母变成大写String s2 = str.toUpperCase();System.out.println(s2);}
}

6 正则表达式

6.1 概述 :

  • 正则表达式通常用来校验,检查字符串是否符合规则的

6.2 体验正则表达式

package com.itheima.regex_demo;import java.util.Scanner;/*设计程序让用户输入一个QQ号码,验证QQ号的合法性:1. QQ号码必须是5--15位长度2. 而且首位不能为03. 而且必须全部是数字*/
public class Test1 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入您的qq号码:");String qq = sc.nextLine();System.out.println(checkQQ2(qq));}private static boolean checkQQ(String qq) {//        1. QQ号码必须是5--15位长度if (qq.length() < 5 || qq.length() > 15) {return false;}
//       2 . 而且首位不能为0if (qq.charAt(0) == '0') {return false;}//        2. 而且必须全部是数字for (int i = 0; i < qq.length(); i++) {char ch = qq.charAt(i);if (ch < '0' || ch > '9') {return false;}}return true;}// 正则表达式改进private static boolean checkQQ2(String qq) {return qq.matches("[1-9][0-9]{4,14}");}
}

6.3 正则表达式的语法

  • boolean matches(正则表达式) :如果匹配正则表达式就返回true,否则返回false
    • boolean matches(正则表达式) :如果匹配正则表达式就返回true,否则返回false
  • 字符类
    • [abc] :代表a或者b,或者c字符中的一个。
    • [^abc]:代表除a,b,c以外的任何字符。
    • [a-z] :代表a-z的所有小写字符中的一个。
    • [A-Z] :代表A-Z的所有大写字符中的一个。
    • [0-9] :代表0-9之间的某一个数字字符。
    • [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
    • [a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符
package com.itheima.regex_demo;
/*字符类 : 方括号被用于指定字符[abc] :代表a或者b,或者c字符中的一个。[^abc]:代表除a,b,c以外的任何字符。[a-z] :代表a-z的所有小写字符中的一个。[A-Z] :代表A-Z的所有大写字符中的一个。[0-9] :代表0-9之间的某一个数字字符。[a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。[a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符需求 :1 验证str是否以h开头,以d结尾,中间是a,e,i,o,u中某个字符2 验证str是否以h开头,以d结尾,中间不是a,e,i,o,u中的某个字符3 验证str是否a-z的任何一个小写字符开头,后跟ad4 验证str是否以a-d或者m-p之间某个字符开头,后跟ad注意: boolean  matches(正则表达式) :如果匹配正则表达式就返回true,否则返回false*/
public class RegexDemo {public static void main(String[] args) {//        1 验证str是否以h开头,以d结尾,中间是a,e,i,o,u中某个字符System.out.println("had".matches("h[aeiou]d"));//        2 验证str是否以h开头,以d结尾,中间不是a,e,i,o,u中的某个字符System.out.println("hwd".matches("h[^aeiou]d"));//        3 验证str是否a-z的任何一个小写字符开头,后跟adSystem.out.println("aad".matches("[a-z]ad"));//        4 验证str是否以a-d或者m-p之间某个字符开头,后跟adSystem.out.println("bad".matches("[a-dm-p]ad"));}
}
  • 逻辑运算符
    • && :并且
    • | :或者
package com.itheima.regex_demo;
/*逻辑运算符 :1 && : 并且2 |  : 或者需求 :1 要求字符串是除a、e、i、o、u外的其它小写字符开头,后跟ad2 要求字符串是aeiou中的某个字符开头,后跟ad*/
public class RegexDemo2 {public static void main(String[] args) {//        1 要求字符串是除a、e、i、o、u外的其它小写字符开头,后跟adSystem.out.println("vad".matches("[a-z&&[^aeiou]]ad"));
//        2 要求字符串是aeiou中的某个字符开头,后跟adSystem.out.println("aad".matches("[a|e|i|o|u]ad"));}
}
  • 预定义字符类
    • “.” : 匹配任何字符。
    • “\d”:任何数字[0-9]的简写;
    • “\D”:任何非数字[^0-9]的简写;
    • “\s” : 空白字符:[ \t\n\x0B\f\r] 的简写
    • “\S” : 非空白字符:[^\s] 的简写
    • “\w” :单词字符:[a-zA-Z_0-9]的简写
    • “\W”:非单词字符:[^\w]
package com.itheima.regex_demo;
/*预定义字符 : 简化字符类的书写"."  :匹配任何字符。"\d" :任何数字[0-9]的简写"\D" :任何非数字[^0-9]的简写"\s" :空白字符:[\t\n\x0B\f\r] 的简写"\S" :非空白字符:[^\s] 的简写"\w" :单词字符:[a-zA-Z_0-9]的简写"\W" :非单词字符:[^\w]需求 :1 验证str是否3位数字2 验证手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字3 验证字符串是否以h开头,以d结尾,中间是任何字符*/
public class RegexDemo3 {public static void main(String[] args) {//        1 验证str是否3位数字System.out.println("123".matches("\\d\\d\\d"));//        2 验证手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字 )System.out.println("15188888888".matches("1[358]\\d\\d\\d\\d\\d\\d\\d\\d\\d"));//        3 验证字符串是否以h开头,以d结尾,中间是任何字符System.out.println("had".matches("h.d"));}
}
  • 数量词
    • X? : 0次或1次
    • X* : 0次到多次
    • X+ : 1次或多次
    • X{n} : 恰好n次
    • X{n,} : 至少n次
    • X{n,m}: n到m次(n和m都是包含的)
package com.itheima.regex_demo;/*数量词 :- X?    : 0次或1次- X*    : 0次到多次- X+    : 1次或多次- X{n}  : 恰好n次- X{n,} : 至少n次- X{n,m}: n到m次(n和m都是包含的)需求 :1 验证str是否3位数字2 验证str是否是多位(大于等于1次)数字3 验证str是否是手机号 ( 1开头,第二位:3/5/8,剩下9位都是0-9的数字)4 验证qq号码:1).5--15位;2).全部是数字;3).第一位不是0*/
public class RegexDemo4 {public static void main(String[] args) {//        1 验证str是否3位数字System.out.println("123".matches("\\d{3}"));//        2 验证str是否是多位(大于等于1次)数字System.out.println("123456".matches("\\d+"));//        3 验证str是否是手机号 ( 1开头,第二位:3/5/8,剩下9位都是0-9的数字)System.out.println("15188888888".matches("1[358]\\d{9}"));//        4 验证qq号码:1).5--15位;2).全部是数字;3).第一位不是0System.out.println("122103987".matches("[1-9]\\d{4,14}"));}
}
  • 分组括号 :
    • 将要重复使用的正则用小括号括起来,当做一个小组看待
package com.itheima.regex_demo;
/*分组括号 : 将要重复使用的正则用小括号括起来,当做一个小组看待需求 :  window秘钥 , 分为5组,每组之间使用 - 隔开 , 每组由5位A-Z或者0-9的字符组成 , 最后一组没有 -举例 :xxxxx-xxxxx-xxxxx-xxxxx-xxxxxDG8FV-B9TKY-FRT9J-99899-XPQ4G分析:前四组其一  :DG8FV-    正则:[A-Z0-9]{5}-最后一组    :XPQ4G     正则:[A-Z0-9]{5}结果 : ([A-Z0-9]{5}-){4}[A-Z0-9]{5}*/
public class RegexDemo5 {public static void main(String[] args) {System.out.println("DG8FV-B9TKY-FRT9J-99899-XPQ4G".matches("([A-Z0-9]{5}-){4}[A-Z0-9]{5}"));}
}
  • 字符串中常用含有正则表达式的方法
    • public String[] split ( String regex ) 可以将当前字符串中匹配regex正则表达式的符号作为"分隔符"来切割字符串。
    • public String replaceAll ( String regex , String newStr ) 可以将当前字符串中匹配regex正则表达式的字符串替换为newStr。
package com.itheima.regex_demo;import java.util.Arrays;/*1 字符串中常用含有正则表达式的方法public String[] split ( String regex ) 可以将当前字符串中匹配regex正则表达式的符号作为"分隔符"来切割字符串。public String replaceAll ( String regex , String newStr ) 可以将当前字符串中匹配regex正则表达式的字符串替换为newStr。需求:1 将以下字符串按照数字进行切割String str1 = "aa123bb234cc909dd";2 将下面字符串中的"数字"替换为"*“aString str2 = "我卡里有100000元,我告诉你卡的密码是123456,要保密哦";*/
public class RegexDemo6 {public static void main(String[] args) {// 1 将以下字符串按照数字进行切割String str1 =  "aa123bb234cc909dd";String[] strs = str1.split("\\d+");System.out.println(Arrays.toString(strs));// 2 将下面字符串中的"数字"替换为"*“aString str2 = "我卡里有100000元,我告诉你卡的密码是123456,要保密哦";System.out.println(str2.replaceAll("\\d+" , "*"));}
}

7 引用数据类型使用

7.1 使用方式

- 基本数据类型可以当做方法的参数,返回值及成员变量使用,传递或者保存的是数据值。
- 引用数据类型也可以当做方法的参数,返回值及字段使用,传递或者保存的是对象的引用(地址)。
- 特别要注意,如果是抽象类或者接口那么传递或者保存的就是子类对象的地址引用了
package com.itheima.datatype_demo;public interface Player {public abstract void play();
}abstract class Mp3Player implements Player {}class IPod extends Mp3Player {@Overridepublic void play() {System.out.println("IPod播放音乐...");}
}
package com.itheima.datatype_demo;/*1 分别定义含有Play,Mp3Player , Ipod参数的方法,并调用传入实参进行测试2  定义一个学生类,里面定义含有Player, Mp3Player,Ipod类型的成员变量创建学生对象并给成员变量赋值*/
public class PlayerTest {public static void main(String[] args) {show1(new IPod());show2(new IPod());show2(new IPod());Student s = new Student();s.setPlayer(new IPod());s.setMp3Player(new IPod());s.setiPod(new IPod());}public static void show1(Player player) {// 方法的参数是一个接口 , 接收实现类对象player.play();}public static void show2(Mp3Player player) {// 方法的参数是一个抽象类 , 接收子类对象player.play();}public static void show3(Mp3Player player) {// 方法的参数是具体的类 , 接收此类对象或者子类对象player.play();}
}/*定义一个学生类,里面定义含有Player, Mp3Player,Ipod类型的成员变量创建学生对象并给成员变量赋值*/
class Student {private Player player;   // 接口的类型的成员变量 , 保存的是实现类对象地址private Mp3Player mp3Player; // 实现类的类型的成员变量 , 保存的是子类对象地址private IPod iPod; // 具体类类型的成员变量 , 保存的是此类对象或者此类的子类对象地址public Player getPlayer() {return player;}public void setPlayer(Player player) {this.player = player;}public Mp3Player getMp3Player() {return mp3Player;}public void setMp3Player(Mp3Player mp3Player) {this.mp3Player = mp3Player;}public IPod getiPod() {return iPod;}public void setiPod(IPod iPod) {this.iPod = iPod;}
}

8 Collection集合

8.1 集合和数组的区别

  • 长度区别
    • 数组 : 长度固定
    • 集合 : 长度可变
  • 存储数据类型
    • 数组 : 可以存储基本数据类型, 也可以存储引用数据类型
    • 集合 : 只能存储引用数据类型 , 要想存储基本数据类型 , 需要存储对应的包装类类型

8.2 集合的体系

8.3 Collection集合常用的方法

  • 在学习集合体系,一般先学习顶层接口。学习了顶层接口的方法,子类型继承而来的方法,就可以不用重复学习。

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

8.4 迭代器

  • 概述 :
    • 迭代器就是对Iterator的称呼 , 专门用来对Collection集合进行遍历使用的。学习迭代器的目的就是为了遍历集合
  • 注意 :
    • 只有继承/实现Iterable接口才具有迭代的能力
    • Collection接口继承了Iterable接口所以 , Collection及其子类都具备迭代的能力
  • 获取迭代器对象的方式
    • 通过Collection集合对象调用Iterable接口中的iterator方法 , 就可以获取迭代器对象
  • Iterator(迭代器)中的方法
    boolean hasNext() 如果迭代具有更多元素,则返回 true 。
    E next() 返回迭代中的下一个元素。
    default void remove() 从底层集合中删除此迭代器返回的最后一个元素(可选操作)。
  • 迭代器的注意事项
    • 当迭代器迭代元素完成后,不能继续next获取元素,否则会报:NoSuchElementException
    • 当迭代器在使用的过程中,不能使用集合对象直接增删元素。会导致报错ConcurrentModificationException。如果要删除可以使用迭代器来删除

8.5 增强for循环

  • 增强for循环(foreach),专门用来遍历集合或者数组,底层实现使用迭代器

  • 定义格式 :

    for(元素的类型 变量名 : 数组/单列集合 ){变量代表的就是集合或者数组的元素
    }
    

    四、 泛型,数据结构,List,Set

学习目标

1 泛型

1.1 泛型的介绍

  • 泛型是一种类型参数,专门用来保存类型用的

    • 最早接触泛型是在ArrayList,这个E就是所谓的泛型了。使用ArrayList时,只要给E指定某一个类型,里面所有用到泛型的地方都会被指定对应的类型

1.2 使用泛型的好处

  • 不用泛型带来的问题

    • 集合若不指定泛型,默认就是Object。存储的元素类型自动提升为Object类型。获取元素时得到的都是Object,若要调用特有方法需要转型,给我们编程带来麻烦.
  • 使用泛型带来的好处
    • 可以在编译时就对类型做判断,避免不必要的类型转换操作,精简代码,也避免了因为类型转换导致的代码异常
 //泛型没有指定类型,默认就是Object
ArrayList list = new ArrayList();
list.add("Hello");
list.add("World");
list.add(100);
list.add(false);
//集合中的数据就比较混乱,会给获取数据带来麻烦
for (Object obj : list) {String str = (String) obj;//当遍历到非String类型数据,就会报异常出错System.out.println(str + "长度为:" + str.length());
}

1.3 泛型的注意事项

  • 泛型在代码运行时,泛型会被擦除。后面学习反射的时候,可以实现在代码运行的过程中添加其他类型的数据到集合

    • 泛型只在编译时期限定数据的类型 , 在运行时期会被擦除

1.4 自定义泛型类

  • 当一个类定义其属性的时候,不确定具体是什么类型时,就可以使用泛型表示该属性的类型

  • 定义的格式
    • 在类型名后面加上一对尖括号,里面定义泛型。一般使用一个英文大写字母表示,如果有多个泛型使用逗号分隔
    • public class 类名<泛型名>{ … }
    举例 :
    public class Student<X,Y>{  X  xObj;
    }
    
  • 泛型的确定
    • 当创建此泛型类是 , 确定泛型类中泛型的具体数据类型
  • 练习
package com.itheima.genericity_demo.genericity_class;import java.time.Period;/*需求 : 定义一个人类,定义一个属性表示爱好,但是具体爱好是什么不清楚,可能是游泳,乒乓,篮球。*/
public class GenericityDemo {public static void main(String[] args) {Person<BasketBall> person = new Person<>();person.setHobby(new BasketBall());Person<Swim> person2 = new Person<>();person2.setHobby(new Swim());Person person3 = new Person<>();// 如果没有指定泛型 , 那么默认使用Object数据类型}
}class Person<H> {// 定义属性表达爱好private H hobby;public H getHobby() {return hobby;}public void setHobby(H hobby) {this.hobby = hobby;}
}class Swim {}class PingPang {}class BasketBall {}

1.3 自定义泛型接口

  • 当定义接口时,内部方法中其参数类型,返回值类型不确定时,就可以使用泛型替代了。

  • 定义泛型接口
    • 在接口后面加一对尖括号 , 尖括号中定义泛型 , 一般使用大写字母表示, 多个泛型用逗号分隔
    • public interface<泛型名> { … }
    • 举例 :
    public interface Collection<E>{public boolean add(E e);
    } 
  • 泛型的确定
    • 实现类去指定泛型接口的泛型
    • 实现了不去指定泛型接口的泛型 , 进行延续泛型 , 回到泛型类的使用
package com.itheima.genericity_demo.genericity_interface;
/*需求:模拟一个Collection接口,表示集合,集合操作的数据不确定。定义一个接口MyCollection具体表示。*/
// 泛型接口
public interface MyCollection<E> {// 添加功能public abstract void add(E e);// 删除功能public abstract void remove(E e);
}// 指定泛型的第一种方式 : 让实现类去指定接口的泛型
class MyCollectionImpl1 implements MyCollection<String>{@Overridepublic void add(String s) {}@Overridepublic void remove(String s) {}
}
// 指定泛型的第二种方式 : 实现类不确定泛型,延续泛型,回到泛型类的使用
class MyCollectionImpl2<E> implements MyCollection<E>{@Overridepublic void add(E a) {}@Overridepublic void remove(E a) {}
}

1.4 自定义泛型方法

  • 当定义方法时,方法中参数类型,返回值类型不确定时,就可以使用泛型替代了

  • 泛型方法的定义
    • 可以在方法的返回值类型前定义泛型
    • 格式 : public <泛型名> 返回值类型 方法名(参数列表){ … }
    • 举例 : public void show(T t) { … }
  • 泛型的确定
    • 当调用一个泛型方法 , 传入的参数是什么类型, 那么泛型就会被确定
  • 练习
    package com.itheima.genericity_demo.genericity_method;import java.util.ArrayList;
    import java.util.Arrays;public class Test {public static void main(String[] args) {// Collection集合中 : public <T> T[] toArray(T[] a) : 把集合中的内容存储到一个数组中 , 进行返回ArrayList<String> list = new ArrayList<>();list.add("abc");list.add("ads");list.add("qwe");String[] array = list.toArray(new String[list.size()]);System.out.println(Arrays.toString(array));}// 接收一个集合 , 往集合中添加三个待指定类型的元素public static <X> void addElement(ArrayList<X> list, X x1, X x2, X x3) {list.add(x1);list.add(x2);list.add(x3);}
    }
    

1.5 通配符

  • 当我们对泛型的类型确定不了,而是表达的可以是任意类型,可以使用泛型通配符给定

    符号就是一个问号:? 表示任意类型,用来给泛型指定的一种通配值。如下

public static void shuffle(List<?> list){//…
} 说明:该方法时来自工具类Collections中的一个方法,用来对存储任意类型数据的List集合进行乱序
  • 泛型通配符结合集合使用

    • 泛型通配符搭配集合使用一般在方法的参数中比较常见。在集合中泛型是不支持多态的,如果为了匹配任意类型,我们就会使用泛型通配符了。
    • 方法中的参数是一个集合,集合如果携带了通配符,要特别注意如下
      • 集合的类型会提升为Object类型
      • 方法中的参数是一个集合,集合如果携带了通配符,那么此集合不能进行添加和修改操作 , 可以删除和获取
    package com.itheima.genericity_demo;import java.util.ArrayList;
    import java.util.List;public class Demo {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("abc");list.add("asd");list.add("qwe");// 方法的参数是一个集合 , 集合的泛型是一个通配符 , 可以接受任意类型元素的集合show(list);}public static void show(List<?> list) {// 如果集合的泛型是一个通配符 , 那么集合中元素以Object类型存在Object o = list.get(0);// 如果集合的泛型是一个通配符 , 那么此集合不能进行添加和修改操作 , 可以删除和获取// list.add(??);// 删除可以list.remove(0);// 获取元素可以for (Object o1 : list) {System.out.println(o1);}}
    }
    
    package com.itheima.genericity_demo;import java.util.ArrayList;/*已知存在继承体系:Integer继承Number,Number继承Object。定义一个方法,方法的参数是一个ArrayList。要求可以接收ArrayList<Integer>,ArrayList<Number>,ArrayList<Object>,ArrayList<String>这些类型的数据。结论 : 具体类型的集合,不支持多态 , 要想接收任意类型集合 , 需要使通配符集合*/
    public class Test1 {public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();ArrayList<Number> list2 = new ArrayList<>();ArrayList<String> list3 = new ArrayList<>();ArrayList<Object> list4 = new ArrayList<>();useList5(list1);useList5(list2);useList5(list3);useList5(list4);}// 此方法只能接收存储Integer类型数据的集合public static void useList1(ArrayList<Integer> list) {}// 此方法只能接收存储Number类型数据的集合public static void useList2(ArrayList<Number> list) {}// 此方法只能接收存储String类型数据的集合public static void useList3(ArrayList<String> list) {}// 此方法只能接收存储Object类型数据的集合public static void useList4(ArrayList<Object> list) {}public static void useList5(ArrayList<?> list) {}}
    

1.6 受限泛型

  • 受限泛型是指,在使用通配符的过程中 , 对泛型做了约束,给泛型指定类型时,只能是某个类型父类型或者子类型

  • 分类 :

    • 泛型的下限 :

      • <? super 类型> //只能是某一类型,及其父类型,其他类型不支持
    • 泛型的上限 :
      • <? extends 类型> //只能是某一个类型,及其子类型,其他类型不支持
    package com.itheima.genericity_demo.wildcard_demo;import java.util.ArrayList;/*wildcardCharacter基于上一个知识点,定义方法show1方法,参数只接收元素类型是Number或者其父类型的集合show2方法,参数只接收元素类型是Number或者其子类型的集合*/
    public class Test2 {public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();ArrayList<Number> list2 = new ArrayList<>();ArrayList<Object> list3 = new ArrayList<>();show1(list3);show1(list2);show2(list2);show2(list1);}// 此方法可以接受集合中存储的是Number或者Number的父类型 , 下限泛型public static void show1(ArrayList<? super Number> list) {}// 此方法可以接受集合中存储的是Number或者Number的子类型 , 上限泛型public static void show2(ArrayList<? extends Number> list) {}
    }
    

2 数据结构

  • 栈结构 : 先进后出

  • 队列结构 : 先进先出

  • 数组结构 : 查询快 , 增删慢

  • 链表结构 : 查询慢 , 增删快

  • 二叉树

    • 二叉树 : 每个节点最多有两个子节点

    • 二茬查找树 : 每个节点的左子节点比当前节点小 , 右子节点比当前节点大

    • 二茬平衡树 : 在查找树的基础上, 每个节点左右子树的高度不超过1

    • 红黑树 :

      • 每一个节点或是红色的,或者是黑色的

      • 根节点必须是黑色

      • 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的

      • 不能出现两个红色节点相连的情况

      • 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

      • 添加元素 :

  • 哈希表结构 :

    • 哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
    • Object类中有一个方法可以获取对象的哈希值
      public int hashCode():返回对象的哈希码值
    • 对象的哈希值特点
      • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
      • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

3 List集合

  • List集合是Collection集合子类型,继承了所有Collection中功能,同时List增加了带索引的功能

  • 特点 :
    • 元素的存取是有序的【有序】
    • 元素具备索引 【有索引】
    • 元素可以重复存储【可重复】
  • 常见的子类
    • ArrayList:底层结构就是数组【查询快,增删慢】
    • Vector:底层结构也是数组(线程安全,同步安全的,低效,用的就少)
    • LinkedList:底层是链表结构(双向链表)【查询慢,增删快】
  • List中常用的方法
    • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
    • public E get(int index):返回集合中指定位置的元素
    • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。\
    • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素
  • LinkedList类
    • LinkedList底层结构是双向链表。每个节点有三个部分的数据,一个是保存元素数据,一个是保存前一个节点的地址,一个是保存后一个节点的地址。可以双向查询,效率会比单向链表高。
    • LinkedList特有方法
      • public void addFirst(E e):将指定元素插入此列表的开头。
      • public void addLast(E e):将指定元素添加到此列表的结尾。
      • public E getFirst():返回此列表的第一个元素。
      • public E getLast():返回此列表的最后一个元素。
      • public E removeFirst():移除并返回此列表的第一个元素。
      • public E removeLast():移除并返回此列表的最后一个元素。

4 Set集合

  • Set集合也是Collection集合的子类型,没有特有方法。Set比Collection定义更严谨
  • 特点 :
    • 元素不能保证插入和取出顺序(无序)
    • 元素是没有索引的(无索引)
    • 元素唯一(元素唯一)
  • Set常用子类
    • HashSet:底层由HashMap,底层结构哈希表结构。
      去重,无索引,无序。
      哈希表结构的集合,操作效率会非常高。
    • LinkedHashSet:底层结构链表加哈希表结构。
      具有哈希表表结构的特点,也具有链表的特点。
    • TreeSet:底层是有TreeMap,底层数据结构 红黑树。
      去重,让存入的元素具有排序(升序排序)

五、排序查找算法,Map集合,集合嵌套,斗地主案例

学习目标 :

1 TreeSet集合

1.1 集合体系

  • Collection

    • List接口

      • ArrayList类
      • LinkedList类
    • Set接口

      • HashSet集合

      • TreeSet集合

1.2 TreeSet特点

  • 不包含重复元素的集合[元素唯一]
  • 没有带索引的方法[无索引]
  • 可以按照指定的规则进行排序[可以排序]

1.3 TreeSet集合的练习

package com.itheima.treeset_demo;import java.util.Iterator;
import java.util.TreeSet;/*1 TreeSet集合练习存储Integer类型的整数,并遍历*/
public class TreeSetDemo {public static void main(String[] args) {TreeSet<Integer> ts = new TreeSet<>();ts.add(10);ts.add(10);ts.add(20);ts.add(10);ts.add(30);// 迭代器Iterator<Integer> it = ts.iterator();while(it.hasNext()){Integer s = it.next();System.out.println(s);}System.out.println("================");// 增强forfor (Integer t : ts) {System.out.println(t);}}
}
  • 如果TreeSet存储自定义对象 , 需要对自定义类进行指定排序规则

    下列代码没有指定排序规则 , 所以运行会报出错误

package com.itheima.treeset_demo;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.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 String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
=============================================================package com.itheima.treeset_demo;import java.util.Iterator;
import java.util.TreeSet;/*TreeSet集合练习存储学生对象,并遍历*/
public class TreeSetDemo2 {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<>();Student s1 = new Student("dilireba", 19);Student s2 = new Student("gulinazha", 20);Student s3 = new Student("maerzhaha", 18);ts.add(s1);ts.add(s2);ts.add(s3);System.out.println(ts);}
}

1.4 排序规则

1.4.1 自然排序

  • 使用步骤
    • 使用空参构造创建TreeSet集合对象
    • 存储元素所在的类需要实现Comparable接口
    • 重写Comparable接口中的抽象方法 compareTo方法,指定排序规则
  • compareTo方法如何指定排序规则 :
    • 此方法如果返回的是小于0 , 代表的是当前元素较小 , 需要存放在左边
    • 此方法如果返回的是大于0 , 代表的是当前元素较大, 需要存放在右边
    • 此方法如果返回的是0 , 代表的是当前元素在集合中已经存在 , 不存储
  • 练习 : 存储学生对象, 按照年龄的升序排序,并遍历
    package com.itheima.treeset_demo;public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.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 String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}/**/@Overridepublic int compareTo(Student o) {/*this : 当前要添加的元素o    : 集合中已经存在的元素如果方法返回值为负数 : 当前元素放左边如果方法的返回值为正数  : 当前元素放右边如果方法的返回值为0  : 说明当前元素在集合中存在,不存储*/int result = this.age - o.age;return result;}
    }
    =====================================================package com.itheima.treeset_demo;
    import java.util.Iterator;
    import java.util.TreeSet;/*TreeSet集合练习存储学生对象,并遍历*/
    public class TreeSetDemo2 {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<>();Student s1 = new Student("dilireba", 19);Student s2 = new Student("gulinazha", 20);Student s3 = new Student("maerzhaha", 18);ts.add(s1);ts.add(s2);ts.add(s3);System.out.println(ts);}
    }
    
    • 对刚才的案例进行改进 , 如果年龄相等 , 那么对学生的名字在字典的顺序排序
    package com.itheima.treeset_demo;public class Student implements Comparable<Student> {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.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 String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}/**/@Overridepublic int compareTo(Student o) {/*this : 当前要添加的元素o    : 集合中已经存在的元素如果方法返回值为负数 : 当前元素放左边如果方法的返回值为正数  : 当前元素放右边如果方法的返回值为0  : 说明当前元素在集合中存在,不存储*/int result = this.age - o.age;// 如果年龄相等 , 那么按照名字进行排序return result == 0 ? this.name.compareTo(o.name) : age;}
    }=============================================================package com.itheima.treeset_demo;import java.util.Iterator;
    import java.util.TreeSet;/*TreeSet集合练习存储学生对象, 按照年龄的升序排序,并遍历*/
    public class TreeSetDemo2 {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<>();Student s1 = new Student("dilireba", 19);Student s2 = new Student("gulinazha", 20);Student s3 = new Student("maerzhaha", 18);Student s4 = new Student("ouyangnanan", 18);ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);System.out.println(ts);}
    }

1.4.2 比较器排序

  • 使用步骤
    • TreeSet的带参构造方法使用的是 “比较器排序” 对元素进行排序的
    • 比较器排序,就是让TreeSet集合构造方法接收Comparator接口的实现类对象
    • 重写Comparator接口中的 compare(T o1,T o2)方法 , 指定排序规则
    • 注意 : o1代表的是当前往集合中添加的元素 , o2代表的是集合中已经存在的元素,排序原理与自然排序相同!
  • 排序规则
    • 排序原理与自然排序相同!
  • 练习
package com.itheima.treeset_demo.comparator_demo;public class Teacher  {private String name;private int age;public Teacher() {}public Teacher(String name, int age) {this.name = name;this.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 String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
======================================package com.itheima.treeset_demo.comparator_demo;import java.util.Comparator;
import java.util.TreeSet;/*TreeSet集合练习存储学生对象, 按照年龄的升序排序,并遍历*/
public class TreeSetDemo2 {public static void main(String[] args) {TreeSet<Teacher> ts = new TreeSet<>(new ComparatorImpl());Teacher s1 = new Teacher("dilireba", 19);Teacher s2 = new Teacher("gulinazha", 20);Teacher s3 = new Teacher("maerzhaha", 18);Teacher s4 = new Teacher("ouyangnanan", 18);ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);System.out.println(ts);}
}// 比较器排序
class ComparatorImpl implements Comparator<Teacher> {@Overridepublic int compare(Teacher o1, Teacher o2) {int result = o1.getAge() - o2.getAge();return result == 0 ? o1.getName().compareTo(o2.getName()) : result;}
}

1.4.3 两种排序的区别

  • 自然排序:自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序。

  • 比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序。

  • 如果Java提供好的类已经定义了自然排序排序规则 , 那么我们可以使用比较器排序进行替换

  • 注意 : 如果自然排序和比较器排序都存在 , 那么会使用比较器排序

  • 两种方式中,关于返回值的规则:

    • 如果返回值为负数,表示当前存入的元素是较小值,存左边
    • 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
    • 如果返回值为正数,表示当前存入的元素是较大值,存右边

2 Collections单列集合工具类

  • Collections工具类介绍

    • java.util.Collections 是集合的工具类,里面提供了静态方法来操作集合,乱序,排序…

2.1 shuffle方法

  • public static void shuffle(List<?> list) 对集合中的元素进行打乱顺序。

  • 集合中元素类型可以任意类型

    package com.itheima.collections_demo;import java.util.ArrayList;
    import java.util.Collections;/*Collections类 : 操作单列集合的工具类public static void shuffle(List<?> list) 对集合中的元素进行打乱顺序1 乱序只能对List集合进行乱序2 集合中元素类型可以任意类型需求 : 定义一个List集合,里面存储若干整数。对集合进行乱序*/
    public class ShuffleDemo {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(50);list.add(40);list.add(20);Collections.shuffle(list);System.out.println(list);// 打印集合中的元素}
    }

2.2 sort方法

  • public static void sort (List list): 对集合中的元素自然排序

    • 该方法只能对List集合进行排序
    • 从方法中泛型分析可知,集合中元素类型必须是Comparable的子类型
    package com.itheima.collections_demo;import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;/*Collections类 : 单列集合的工具类sort方法是一个重载的方法,可以实现自然排序及比较器排序。要特别注意的是sort方法只能对List集合进行排序,方法如下:public static <T extends Comparable> void sort (List<T> list)练习:定义List集合,存储若干整数,进行排序*/
    public class SortDemo1 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(3);list.add(2);list.add(4);list.add(1);// 使用此方法 , 需要集合中存储的元素实现Comparable接口Collections.sort(list);System.out.println(list);}
    }
    
  • public static void sort (List list, Comparator<? super T> c)

    • 方法只能对List集合排序

    • 对元素的类型没有要求

    • 需要定义一个比较器Comparator (规则和之前TreeSet时一样)

    • 使用场景:

      • List集合中的元素类型不具备自然排序能力(元素类型没有实现结果 Comparable)
      • List集合中的元素类型具备自然排序能力,但是排序规则不是当前所需要的。
      package com.itheima.collections_demo;import java.util.ArrayList;
      import java.util.Collections;
      import java.util.Comparator;/*Collections类 : 单列集合的工具类sort方法是一个重载的方法,可以实现自然排序及比较器排序。要特别注意的是sort方法只能对List集合进行排序,方法如下:public static <T extends Comparable> void sort (List<T> list) : 只能对集合中的元素自然排序需求1:定义一个List集合,存储若干整数,要求对集合进行降序排序分析:整数类型Integer具备自然排序能力,但是题目要求降序排序需求2:定义一个学生类,属性有姓名,年龄。创建若干对象放到List集合中。要求对List集合中学生对象进行年龄的升序排序。分析:自定义类型默认是没有自然排序能力的,我们使用自定义比较器方式排序。*/
      public class SortDemo2 {public static void main(String[] args) {/*需求2:定义一个学生类,属性有姓名,年龄。创建若干对象放到List集合中。要求对List集合中学生对象进行年龄的升序排序。分析:自定义类型默认是没有自然排序能力的,我们使用自定义比较器方式排序*/ArrayList<Student> list = new ArrayList<>();list.add(new Student("lisi", 24));list.add(new Student("zhangsan", 23));Collections.sort(list, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();}});System.out.println(list);}/*需求1:定义一个List集合,存储若干整数,要求对集合进行降序排序分析:整数类型Integer具备自然排序能力,但是题目要求降序排序*/private static void method1() {ArrayList<Integer> list = new ArrayList<>();list.add(3);list.add(2);list.add(4);list.add(1);// 使用此方法 , 需要集合中存储的元素实现Comparable接口Collections.sort(list, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});System.out.println(list);}
      }
      

3 可变参数

3.1 可变参数介绍

  • 在 JDK5 中提供了可变参数,允许在调用方法时传入任意个参数。可变参数原理就是一个数组形式存在
  • 格式 : 修饰符 返回值类型 方法名(数据类型… 变量名) { }
  • 举例 : public void show(int … num) : 表达式该方法可以接收任意个整数值 , 原理 : 其实就是一个int类型的数组

3.2 可变参数注意

  • 可变参数只能作为方法的最后一个参数,但其前面可以有或没有任何其他参数。
  • 可变参数本质上是数组,不能作为方法的重载。如果同时出现相同类型的数组和可变参数方法,是不能编译通过的。

3.3 可变参数的使用

  • 调用可变参数方法,可以给出零到任意多个参数,编译器会将可变参数转化为一个数组,也可以直接传递一个数组。
    方法内部使用时直接当做数组使用即可
package com.itheima.changevariable_demo;/*1 什么是可变参数JDK5中,允许在调用方法时传入任意个参数。可变参数原理就是一个数组形式存在格式 : 修饰符 返回值类型 方法名(数据类型… 变量名) {  }举例 : public void show(int... num){}2 可变参数注意 :1) 可变参数只能作为方法的最后一个参数,但其前面可以有或没有任何其他参数。2) 可变参数本质上是数组,不能作为方法的重载。如果同时出现相同类型的数组和可变参数方法,是不能编译通过的。3 可变参数的使用 :调用可变参数的方法 , 可以传入0个到任意个数据 , 编译器会将可变参数转换成一个数组 , 也可以直接传递一个数组方法中把可变参数当做一个数组去使用即可练习:定义方法可以求任意个整数的和*/
public class VariableDemo1 {public static void main(String[] args) {sum();sum(1, 2);sum(1, 2, 3, 4);}public static void sum(int... num) {// 方法的参数是一个int类型的可变参数int sum = 0;// 定义求和变量for (int i : num) {sum += i;}System.out.println(sum);}
}

3.4 addAll方法

  • static boolean addAll(Collection<? super T> c , T… elements) : 添加任意多个数据到集合中

    • 该方法就是一个含有可变参数的方法,使用时可以传入任意多个实参,实用方便!

    • 分析 : Collection<? super T> , ? 可以是 T 的类型或者父类型 , 反过来 , T是?类型或者子类型

      那么当你确定?的类型,也就是集合的类型 , 就可以往集合中添加此类型或者子类型

    package com.itheima.changevariable_demo;import java.util.ArrayList;
    import java.util.Collections;/*Collections的addAll方法static <T> boolean  addAll(Collection<? super T> c , T... elements) : 添加任意多个数据到集合中分析: 该方法就是一个含有可变参数的方法,使用时可以传入任意多个实参,实用方便!练习:创建一个List集合,使用addAll方法传入若干字符串*/
    public class VariableDemo2 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 10, 20, 30, 40);System.out.println(list);// [10, 20, 30, 40]}
    }

4 排序,查找算法

4.1 冒泡排序

  • 冒泡排序 : 将一组数据按照从小到大的顺序进行排序
  • 冒泡排序原理 : 相邻元素两两作比较 , 大的元素往后放
package com.itheima.arraysort_demo.bubblesort_demo;import java.util.Arrays;/*冒泡排序 : 将一组数据按照从小到大的顺序进行排序冒泡排序的原理 : 相邻元素两两作比较 , 大的元素往后放需求 : 将数组中的元素 {3,5,2,1,4} 进行升序排序*/
public class SortDemo {public static void main(String[] args) {int[] arr = {3, 5, 2, 1, 4};//        // 第一轮排序
//        for (int i = 0; i < arr.length - 1; i++) {//            if (arr[i] > arr[i + 1]) {//                int temp = arr[i];
//                arr[i] = arr[i + 1];
//                arr[i + 1] = temp;
//            }
//        }
//
//        System.out.println("第一轮排序:" + Arrays.toString(arr));
//
//
//        // 第二轮排序
//        for (int i = 0; i < arr.length - 2; i++) {//            if (arr[i] > arr[i + 1]) {//                int temp = arr[i];
//                arr[i] = arr[i + 1];
//                arr[i + 1] = temp;
//            }
//        }
//
//        System.out.println("第二轮排序:" + Arrays.toString(arr));
//
//
//        // 第三轮排序
//        for (int i = 0; i < arr.length - 2; i++) {//            if (arr[i] > arr[i + 1]) {//                int temp = arr[i];
//                arr[i] = arr[i + 1];
//                arr[i + 1] = temp;
//            }
//        }
//
//        System.out.println("第三轮排序:" + Arrays.toString(arr));
//
//
//        // 第四轮排序
//        for (int i = 0; i < arr.length - 2; i++) {//            if (arr[i] > arr[i + 1]) {//                int temp = arr[i];
//                arr[i] = arr[i + 1];
//                arr[i + 1] = temp;
//            }
//        }
//
//        System.out.println("第四轮排序:" + Arrays.toString(arr));// 优化代码for (int j = 0; j < arr.length - 1; j++) {// 比较的轮次// 每轮相邻元素比较的次数for (int i = 0; i < arr.length - 1 - j; i++) {if (arr[i] > arr[i + 1]) {int temp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = temp;}}System.out.println("第" + (j + 1) + "轮排序:" + Arrays.toString(arr));}}
}

4.2 选择排序

  • 选择排序原理 : 它的工作原理是每一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。
  • 注意事项 :
    • 有n个元素,那么就要比较n-1轮次。
    • 每一趟中都会选出一个最值元素,较前一趟少比较一次
package com.itheima.arraysort_demo.selectionsort_demo;
/*选择排序工作原理 :它的工作原理是每一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。注意 :1 有n个元素,那么就要比较n-1趟。2 每一趟中都会选出一个最值元素,较前一趟少比较一次*/import java.util.Arrays;public class SortDemo {public static void main(String[] args) {int[] arr = {4, 1, 5, 3, 2};// 遍历数组for (int i = 0; i < arr.length - 1; i++) {// 记录当前元素和其之后所有元素的最小值索引int minIndex = i;int min = arr[i];for (int j = i; j < arr.length; j++) {if (arr[j] < min) {minIndex = j; //  把当前最小值的索引赋值给minIndexmin = arr[j];// 替换最小值}}if (i != minIndex) {int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}System.out.println(Arrays.toString(arr));}
}

4.3 二分查找

  • 原理 : 每次去掉一般的查找范围
  • 前提 : 数组必须有序
package com.itheima.arraysort_demo.binarysearch_demo;/*二分查找 :原理 : 每次去掉一般的查找范围前提 : 数组必须有序步骤 :1,定义两个变量,表示要查找的范围。默认min = 0 , max = 最大索引2,循环查找,但是min <= max3,计算出mid的值4,判断mid位置的元素是否为要查找的元素,如果是直接返回对应索引5,如果要查找的值在mid的左半边,那么min值不变,max = mid -1.继续下次循环查找6,如果要查找的值在mid的右半边,那么max值不变,min = mid + 1.继续下次循环查找7,当 min > max 时,表示要查找的元素在数组中不存在,返回-1.*/
public class BinarySearchDemo {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int i = binarySearch(arr, 8);System.out.println(i);}public static int binarySearch(int[] arr, int num) {// 定义两个变量,表示要查找的范围。默认min = 0 , max = 最大索引int max = arr.length - 1;int min = 0;// 2,循环查找,但是min <= maxwhile (min <= max) {// 3,计算出mid的值int mid = (min + max) / 2;if (arr[mid] == num) {//  4,判断mid位置的元素是否为要查找的元素,如果是直接返回对应索引return mid;} else if (arr[mid] > num) {// 5,如果要查找的值在mid的左半边,那么min值不变,max = mid -1.继续下次循环查找max = mid - 1;} else if (arr[mid] < num) {// 6,如果要查找的值在mid的右半边,那么max值不变,min = mid + 1.继续下次循环查找min = mid + 1;}}return -1;}
}

5 Map集合

5.1 Map集合的介绍

  • java.util.Map<K,V> 集合,里面保存的数据是成对存在的,称之为双列集合。存储的数据,我们称为键值对。 之前所学的Collection集合中元素单个单个存在的,称为单列集合

5.2 特点

  • Map<K,V> K:键的数据类型;V:值的数据类型

  • 特点 :

    • 键不能重复,值可以重复
    • 键和值是 一 一 对应的,通过键可以找到对应的值
    • (键 + 值) 一起是一个整体 我们称之为“键值对” 或者 “键值对对象”,在Java中叫做“Entry对象”
  • 使用场景

    • 凡是要表示一一对应的数据时就可以Map集合

      • 举例 : 学生的学号和姓名 — (itheima001 小智)
      • 举例 : 夫妻的关系 ---- (王宝强 马蓉 ) (谢霆锋 张柏芝)

5.3 常用实现类

  • HashMap:

    • 此前的HashSet底层实现就是HashMap完成的,HashSet保存的元素其实就是HashMap集合中保存的键,底层结构是哈希表结构,具有键唯一,无序,特点。
  • LinkedHashMap:
    • 底层结构是有链表和哈希表结构,去重,有序
  • TreeMap:
    • 底层是有红黑树,去重,通过键排序

5.4 常用的方法

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
  • public Set keySet(): 获取Map集合中所有的键,存储到Set集合中。
  • public boolean containKey(Object key):判断该集合中是否有此键。
package com.itheima.map_demo.mapmethod_demo;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*Map中常用方法 :public V put(K key, V value):  把指定的键与指定的值添加到Map集合中public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值public V get(Object key) 根据指定的键,在Map集合中获取对应的值public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中public boolean containKey(Object key): 判断该集合中是否有此键。需求 : 将以下数据保存到Map集合中 , 进行测试以上方法“文章“       "马伊琍“谢霆锋”     “王菲”“李亚鹏”     “王菲”*/
public class MapDemo {public static void main(String[] args) {//  创建双列集合对象Map<String, String> hm = new HashMap<>();// 添加元素// public V put(K key, V value):  把指定的键与指定的值添加到Map集合中hm.put("文章", "马伊琍");hm.put("谢霆锋", "王菲");hm.put("李亚鹏", "王菲");// public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值// System.out.println(hm.remove("谢霆锋"));// public V get(Object key) 根据指定的键,在Map集合中获取对应的值// System.out.println(hm.get("李亚鹏"));// public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中
//        Set<String> set = hm.keySet();
//        for (String key : set) {//            System.out.println(key);
//        }// public boolean containKey(Object key): 判断该集合中是否有此键。// System.out.println(hm.containsKey("李亚鹏"));System.out.println(hm);// 打印集合 , 打印的是集合中的元素}
}

5.5 Map集合的遍历

  • 第一种方式 : 键找值
    package com.itheima.map_demo.map_test;
    

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
创建Map集合对象 , 往集合中添加以下四对元素 , 使用键找值遍历集合

周瑜 -- 小乔
孙策 -- 大乔
刘备 -- 孙尚香
诸葛亮 -- 黄月英

*/
public class MapTest1 {
public static void main(String[] args) {
// 创建集合对象
Map<String, String> hm = new HashMap<>();

    // 添加元素hm.put("周瑜", "小乔");hm.put("孙策", "大乔");hm.put("刘备", "孙尚香");hm.put("诸葛亮", "黄月英");// 获取健集合Set<String> set = hm.keySet();// 遍历健集合 , 通过键找值for (String key : set) {String value = hm.get(key);System.out.println(key + "---" + value);}
}

}

- 第二种方式  : 获取键值对对象 , 在找到键和值​```java
package com.itheima.map_demo.map_test;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*需求 :  创建Map集合对象 , 往集合中添加以下三对元素使用获取Entry对象集合,在找到键和值 遍历集合张无忌 -- 赵敏张翠山 -- 殷素素张三丰 -- 郭芙*/
public class MapTest2 {public static void main(String[] args) {// 创建集合对象Map<String, String> hm = new HashMap<>();// 添加元素hm.put("张无忌", "赵敏");hm.put("张翠山", "殷素素");hm.put("张三丰", "郭芙");// 获取键值对对象集合Set<Map.Entry<String, String>> set = hm.entrySet();// 遍历键值对对象集合 , 获取每一个键值对对象for (Map.Entry<String, String> entry : set) {// 通过entry对象获取键String key = entry.getKey();// 通过entry对象获取值String value = entry.getValue();System.out.println(key + "--" + value);}}
}

5.6 HashMap集合

  • 注意 : HashMap集合 , 要想保证键唯一 , 那么键所在的类必须重写hashCode和equals方法
package com.itheima.map_demo.map_test;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.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 boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
package com.itheima.map_demo.map_test;
import java.util.HashMap;
import java.util.Set;/*HashMap类 :存储数据,每位学生(姓名,年龄)都有自己的家庭住址。学生和地址有对应关系,将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。要求:学生姓名相同并且年龄相同视为同一名学生,不能重复存储*/
public class HashMapTest {public static void main(String[] args) {// 学生作为键, 家庭住址作为值。HashMap<Student, String> hm = new HashMap<>();hm.put(new Student("迪丽热巴", 18) , "新疆");hm.put(new Student("迪丽热巴", 18) , "中国");Set<Student> set = hm.keySet();for (Student key : set) {String value = hm.get(key);System.out.println(key + "--" + value);}}
}

5.7 LinkedHashMap集合

  • LinkedHashMap类 , 在最底层采用的数据结构 : 是链表+哈希表。
  • 特点 :
    • 元素唯一
    • 元素有序
package com.itheima.map_demo.map_test;import java.util.LinkedHashMap;
import java.util.Set;/*LinkedHashMap类 , 在最底层采用的数据结构 : 是链表+哈希表。特点 :1 元素唯一2 有序需求 : 创建LinkedHashMap对象 , 添加元素进行验证 元素唯一 , 有序的特点*/
public class LinkedHashMapTest {public static void main(String[] args) {// 创建集合对象LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put(1, "张三");linkedHashMap.put(1, "李四");linkedHashMap.put(2, "王五");linkedHashMap.put(3, "赵六");System.out.println(linkedHashMap);}
}

5.8 TreeMap集合

  • TreeMap的底层是红黑树实现的,有排序的能力,键去重。

  • 可以自然排序(键所在的类要实现Comparable)

  • 若自定义类没有自然排序功能,或自然排序功能不满足要求时。可以自定义比较器排序(Comparator)

package com.itheima.map_demo.map_test;
import java.util.TreeMap;/*需求 :定义TreeMap集合存储键值对,键使用Integer,值使用String,存储若干键值对,遍历集合观察结果是否有排序。*/
public class TreeMapTest1 {public static void main(String[] args) {//  定义TreeMap集合存储键值对,键使用Integer,值使用String// 创建集合对象TreeMap<Integer, String> treeMap = new TreeMap<>();treeMap.put(1, "张三");treeMap.put(3, "赵六");treeMap.put(2, "王五");System.out.println(treeMap);}
}
package com.itheima.map_demo.map_test;import java.util.Comparator;
import java.util.TreeMap;/*需求:创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String)。学生属性姓名和年龄, 要求按照年龄进行升序排序并遍历*/
public class TreeMapTest2 {public static void main(String[] args) {// 学生作为键, 家庭住址作为值。TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();}});tm.put(new Student("迪丽热巴", 18), "新疆");tm.put(new Student("迪丽热巴", 16), "中国");System.out.println(tm);}
}

6 集合嵌套

6.1 List嵌套List

package com.itheima.Collection_nested_demo;import java.util.ArrayList;
import java.util.List;/*使用场景举例:一年级有多个班级,每个班级有多名学生。要求保存每个班级的学生姓名,保存一个年级所有的班级信息思路:可以使用List集合保存一个班级的学生可以使用List集合保存所有班级因此我们可以定义集合如下:班级:List<String>举例 :List<String> 三年一班 = {迪丽热巴 , 古力娜扎 ,马尔扎哈 ,欧阳娜娜}List<String> 三年二班 = {李小璐 , 白百何 , 马蓉}List<String> 三年三班 = {林丹 ,文章, 陈赫}年级:List<List<String>>举例 :List<List<String>> 年级 = {三年一班 , 三年二班 , 三年三班}*/
public class Test3 {public static void main(String[] args) {List<String> 三年一班 = new ArrayList<>();三年一班.add("迪丽热巴");三年一班.add("古力娜扎");三年一班.add("马尔扎哈");三年一班.add("欧阳娜娜");List<String> 三年二班 = new ArrayList<>();三年二班.add("李小璐");三年二班.add("白百何");三年二班.add("马蓉");List<String> 三年三班 = new ArrayList<>();三年三班.add("林丹");三年三班.add("文章");三年三班.add("陈赫");List<List<String>> 年级 = new ArrayList<>();年级.add(三年一班);年级.add(三年二班);年级.add(三年三班);for (List<String> 班级 : 年级) {for (String name : 班级) {System.out.println(name);}System.out.println("-----------------");}}
}

6.2 List嵌套Map

package com.itheima.Collection_nested_demo;import java.util.*;/*List嵌套Map :使用场景举例:一年级有多个班级,每个班级有多名学生。要求保存每个班级的学生姓名,姓名有与之对应的学号,保存一年级所有的班级信息。思路:1 可以使用Map集合保存一个班级的学生(键是学号,值是名字)2 可以使用List集合保存所有班级因此我们可以定义集合如下:班级:Map<String,String> 键是学号,值是姓名举例 :Map<String,String> 三年一班 = {it001 = 迪丽热巴 , it002 = 古力娜扎 ,it003 = 马尔扎哈 ,it004 = 欧阳娜娜}Map<String,String> 三年二班 = {it001 = 李小璐 , it002 = 白百何 , it003 = 马蓉}Map<String,String> 三年三班 = {it001 = 林丹 ,it002 = 文章, it003 = 陈赫}年级:List<Map<String,String>>保存每个班级的信息举例 :List<Map<String,String>> 年级 = {三年一班 , 三年二班 , 三年三班}*/
public class Test2 {public static void main(String[] args) {Map<String, String> 三年一班 = new HashMap<>();三年一班.put("it001", "迪丽热巴");三年一班.put("it002", "古力娜扎");三年一班.put("it003", "马尔扎哈");三年一班.put("it004", "欧阳娜娜");Map<String, String> 三年二班 = new HashMap<>();三年二班.put("it001", "李小璐");三年二班.put("it002", "白百何");三年二班.put("it003", "马蓉");Map<String, String> 三年三班 = new HashMap<>();三年三班.put("it001", "林丹");三年三班.put("it002", "文章");三年三班.put("it003", "陈赫");List<Map<String, String>> 年级 = new ArrayList<>();年级.add(三年一班);年级.add(三年二班);年级.add(三年三班);for (Map<String, String> 班级 : 年级) {Set<String> studentId = 班级.keySet();for (String id : studentId) {String name = 班级.get(id);System.out.println(id + "---" + name);}System.out.println("=================");}}
}

6.3 Map嵌套Map

package com.itheima.Collection_nested_demo;import java.util.*;/*Map嵌套Map使用场景举例:一个年级有多个班级,每个班级有多名学生。要求保存每个班级的学生姓名,姓名有与之对应的学号,保存一年级所有的班级信息,班级有与之对应的班级名称。思路:可以使用Map集合保存一个班级的学生(键是学号,值是名字)可以使用Map集合保存所有班级(键是班级名称,值是班级集合信息)因此我们可以定义集合如下:班级: Map<String,String> 键:学号,值:姓名举例 :Map<String,String> 三年一班 = {it001 = 迪丽热巴 , it002 = 古力娜扎 ,it003 = 马尔扎哈 ,it004 = 欧阳娜娜}Map<String,String> 三年二班 = {it001 = 李小璐 , it002 = 白百何 , it003 = 马蓉}Map<String,String> 三年三班 = {it001 = 林丹 ,it002 = 文章, it003 = 陈赫}年级: Map<String , Map<String,String>> 键:班级名称,值:具体班级信息举例:Map<String, Map<String,String>> 年级 = {"三年一班" = 三年一班 , "三年二班" = 三年二班 , "三年三班" = 三年三班 }*/
public class Test3 {public static void main(String[] args) {Map<String, String> 三年一班 = new HashMap<>();三年一班.put("it001", "迪丽热巴");三年一班.put("it002", "古力娜扎");三年一班.put("it003", "马尔扎哈");三年一班.put("it004", "欧阳娜娜");Map<String, String> 三年二班 = new HashMap<>();三年二班.put("it001", "李小璐");三年二班.put("it002", "白百何");三年二班.put("it003", "马蓉");Map<String, String> 三年三班 = new HashMap<>();三年三班.put("it001", "林丹");三年三班.put("it002", "文章");三年三班.put("it003", "陈赫");Map<String, Map<String, String>> 年级 = new HashMap<>();年级.put("三年一班", 三年一班);年级.put("三年二班", 三年二班);年级.put("三年三班", 三年三班);Set<String> 班级名字集合 = 年级.keySet();for (String 班级名字 : 班级名字集合) {Map<String, String> 班级信息 = 年级.get(班级名字);Set<String> 学生学号 = 班级信息.keySet();for (String 学号 : 学生学号) {String 姓名 = 班级信息.get(学号);System.out.println("班级名字:" + 班级名字 + " ,学号:" + 学号 + " , 名字:" + 姓名);}System.out.println("============");}}
}

7 斗地主案例

package com.itheima.doudizhu;import java.util.*;/*按照斗地主的规则,完成洗牌发牌的动作。要求完成以下功能:准备牌:组装54张扑克牌洗牌:54张牌顺序打乱发牌:三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。看牌:查看三人各自手中的牌(按照牌的大小排序)、底牌规则:手中扑克牌从大到小的摆放顺序:大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3*/
public class DouDiZhu {public static void main(String[] args) {// 准备牌// 键我牌的序号 , 值为牌面HashMap<Integer, String> pokers = new HashMap<>();// 牌的颜色String[] colors = {"♠", "♥", "♣", "♦"};String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};int count = 2;for (String number : numbers) {// 3for (String color : colors) {// System.out.println(count + " = " + color + number);pokers.put(count, color + number);count++;}}pokers.put(0, "大王");pokers.put(1, "小王");System.out.println(pokers);// 洗牌Set<Integer> set = pokers.keySet();// 创建存储编号的list集合List<Integer> list = new ArrayList<>();// {10 , 6 , 8 , 20 , 22 , 11 ... }// 把set集合中的元素存储到list集合中list.addAll(set);// 打乱集合中编号Collections.shuffle(list);System.out.println(list);// 发牌TreeSet<Integer> 赌神 = new TreeSet<>();TreeSet<Integer> 赌圣 = new TreeSet<>();TreeSet<Integer> 赌侠 = new TreeSet<>();TreeSet<Integer> 底牌 = new TreeSet<>();// 遍历牌的编号for (int i = 0; i < list.size() - 3; i++) {if (i % 3 == 0) {赌神.add(list.get(i));} else if (i % 3 == 1) {赌圣.add(list.get(i));} else {赌侠.add(list.get(i));}}底牌.add(list.get(51));底牌.add(list.get(52));底牌.add(list.get(53));System.out.println("赌神:" + 赌神);System.out.println("赌圣:" + 赌圣);System.out.println("赌侠:" + 赌侠);System.out.println("底牌:" + 底牌);// 看牌// 赌神lookPoker(pokers, 赌神, "赌神:  ");// 赌圣lookPoker(pokers, 赌圣, "赌圣:  ");// 赌侠lookPoker(pokers, 赌侠, "赌侠:  ");// 底牌System.out.print("底牌:  ");for (Integer integer : 底牌) {String poker = pokers.get(integer);System.out.print(poker + "\t");}}private static void lookPoker(HashMap<Integer, String> pokers, TreeSet<Integer> 赌神, String s) {System.out.print(s);for (Integer integer : 赌神) {String poker = pokers.get(integer);System.out.print(poker + "\t");}System.out.println();}
}

Java基础巩固(一)类,接口,枚举,常用API,集合,泛型,正则,数据结构相关推荐

  1. JAVA基础知识二(面向对象、常用API)

    五.面相对象 1.面向对象 面向过程和面向对象都是解决问题的一种思想模式. 面向过程:指的就是按照一定的步骤,逐一执行,将问题进行解决. 相当于是一个 执行者 角色. 面向对象:指的就是找对象(对象内 ...

  2. Java基础系列(十四)常用API

    常用API 一.基本类型包装类 1.1.将字符串转成基本类型 1.2.将基本类型转成字符串 二.System类 三.Math类 四.Array类 一.基本类型包装类 基本数据类型对象包装类特点:用于在 ...

  3. 【狂神说笔记—— Java基础07-常用类】

    Java基础07-常用类 Object类 大家都知道Object是所有类的父类,任何类都默认继承Object. 理论上Object类是所有类的父类,即直接或间接的继承java.lang.Object类 ...

  4. 多重继承_Python 和 Java 基础对比 10 —— 类的封装、继承和多态

    @Python大星 一.Python 类的封装.继承和多态 封装 继承 Python 支持多父类的继承机制,所以需要注意圆括号中基类的顺序,若是基类中有相同的方法名,并且在子类使用时未指定,Pytho ...

  5. Java基础:String类

    相关阅读 Java基础:String类 Java字符串格式化 Java基础:正则表达式 1. 概述 字符串是由多个字符组成的一串数据(字符序列),字符串可以看成是字符数组. 在实际开发中,字符串的操作 ...

  6. 初学Java基础学习——抽象类和接口的区别

    初学Java基础学习--抽象类和接口的区别 一.关键字 1)抽象类的关键字 abstract class A{//定义一个抽象类: } class Test extends A{//子类使用exten ...

  7. 第一阶段>>>Java基础进阶 OOP/Reflect/注解/IO流/API核心

    目录 >>>java基础01-结构以及类型 >>>java基础02-初识数组 >>>java基础03-面向对象OOP >>>ja ...

  8. java金蝶星空云金蝶Java 对接 金蝶云星空 接口 对接 金蝶API 对接 金蝶 接口 解决 会话失效 问题 会话已失效,请重新登录

    java金蝶星空云金蝶Java 对接 金蝶云星空 接口 对接 金蝶API 对接 金蝶 接口 解决 会话失效 问题 会话已失效,请重新登录 1.准备工作 1.1 接口调用账户 1.2 下载 金蝶星空云 ...

  9. Java基础23-集合类2(Set接口,Iterator迭代器)

    一.Set接口简介 根据API,Set接口是一个不包含重复元素的 collection.更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null ...

  10. JAVA(四)类集/枚举

    成鹏致远 | lcw.cnblog.com |2014-02-04 JAVA类集 1.认识类集 类集的作用 类集实际上就是一个动态的对象数组,与一般的对象数组不同,类集中的对象内容可以任意扩充 类集的 ...

最新文章

  1. indent 的格式
  2. android studio 第一个程序显示radle d 'https://services.gradle.org/distributions/gradle-5.4.1-all.zip'.
  3. MYSQL查表的字段名称,字段类型,字段长度,字段注释的SQL语句
  4. Eclipse设置项目默认编码和换行符类型
  5. oracle 11 导入到 10,oracle11g导入到10g
  6. Cloudera发布全球企业数据成熟度报告,混合云趋势中有效数据战略是关键
  7. 基于JAVA+SpringBoot+Mybatis+MYSQL的课程评价系统
  8. 第十三节:使用Lombok简化你的代码
  9. 微信小程序的三级分销-项目表格设计
  10. java实现电话的呼叫转移_「呼叫转移设置」呼叫转移流程分析(一) - seo实验室...
  11. 移动物联网卡哪里可以办理
  12. 数据重生:让神经机器翻译中的不活跃样本“复活”
  13. 汽车标志你认识多少?爱车族一定要了解哦!
  14. SQL数据库快照删除
  15. android生成md5,使用Android studio生成签名文件以及获取MD5
  16. 再携手,齐并进!菊风助力宁波银行坐席PUSH外呼项目
  17. 基于Spring+SpringMVC+MyBatis博客系统的开发教程(十三)
  18. Google谷歌未来如何占领“Web3高地”?
  19. 002.2-地下管线转3dtiles工具
  20. c语言程序打不开如何修复,处理win7中打不开程序修复0xc0000142错误代码的问题

热门文章

  1. 同一个SSH公钥同时用于Github和Gitee
  2. 【历史上的今天】9 月 10 日:互联网上第一个搜索工具诞生;微软首席架构师出生;马云诞生
  3. 分享一个可以自定义搜索定位的地图
  4. vmware安装hadoop(多台机相连)(二)
  5. 《追风筝的人》的寓意读后感3200字
  6. iPhone11 Pro 官方壁纸原图
  7. 基于Qualcomm骁龙处理器的目标跟随与导航程序源代码
  8. 中国地质大学武汉计算机学院保研率,中国地质大学(武汉)2021届保研人数,宿舍8人全保研是亮点...
  9. oc引导开机直接进_利用OC Gen X工具适配自己的OC引导
  10. STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集