枚举
1)枚举对应英文(enumeration,简写enum)
2)枚举是一组常量的集合。
3)可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。
枚举的二种实现方式
1)自定义类实现枚举
2)使用enum关键字实现枚举
自定义类实现枚举-应用案例
1.不需要提供setXxx方法,因为枚举对象值通常为只读.
2.对枚举对象/属性使用final + static共同修饰,实现底层优化.
3.枚举对象名通常使用全部大写,常量的命名规范.
4.枚举对象根据需要,也可以有多个属性
小结:进行自定义类实现枚举,有如下特点:
1)构造器私有化
2)本类内部创建一组对象门
3)对外暴露对象(通过为对象添加public final static修饰符)
4)可以提供get方法,但是不要提供set
package com.dxl.staticpar;
public class Enumweration {
public static void main(String[] args) {
System.out.println(Season.AUTUMN);
}
}
class Season{
private String name;
private String desc;
public final static Season SPRING = new Season("春天","温暖");
public final static Season WINTER = new Season("冬天","寒冷");
public final static Season AUTUMN = new Season("秋天","凉爽");
public final static Season SUNMMER = new Season("夏天","炎热");
// 1.将构造器私有化
// 2.去掉set方法,防止属性被修改
// 3.在内部创建固定的值
// 4.优化:在加入一个final关键字
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
使用关键字enum来实现枚举类
package com.dxl.staticpar;
public class Enumweration {
public static void main(String[] args) {
System.out.println(Season2.AUTUMN);
}
}
enum Season2{
// public final static Season SPRING = new Season("春天","温暖");
// public final static Season WINTER = new Season("冬天","寒冷");
// public final static Season AUTUMN = new Season("秋天","凉爽");
// public final static Season SUNMMER = new Season("夏天","炎热");
// 如果使用enum来实现枚举类
// 1.使用关键字 enum 替代 class
// 2.原来的 public final static Season SPRING = new Season("春天","温暖");
// 使用 SPRING("春天","温暖"); 替代
// 3.如果有多个常量,用逗号间隔
// 4.如果使用enum 来实现枚举,要求将定义常量对象写在最前面。
SPRING("春天","温暖"), WINTER("冬天","寒冷"),
AUTUMN("秋天","凉爽"), SUNMMER("夏天","炎热");
private String name;
private String desc;//描述
// 1.将构造器私有化
// 2.去掉set方法,防止属性被修改
// 3.在内部创建固定的值
// 4.优化:在加入一个final关键字
private Season2(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
enum关键字实现枚举
enum关键字实现枚举注意事项
1.当我们使用enum关键字开发一个枚举类时,默认会继承Enum类[如何证明]
2.传统的 public static final Season2 SPRING = new Season2(春天",“温暖“”);简化成 SPRING(“春天”,“温暖”),这里必须知道,它调用的是哪个构造器.
3.如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
4.当有多个枚举对象时,使用,间隔,最后有一个分号结尾
5.枚举对象必须放在枚举类的行首.
enum常用方法说明
说明:使用关键字enum时,会隐式继承Enum类,这样我们就可以使用Enum类相关的方法。
public abstract class Enum<E extends Enum>
implements Comparable, Serializable {
}
1.toString:Enum类已经重写过了,返回的是当前对象名.子类可以重写该方法,用于返回对象的属性信息
2. name:返回当前对象名(常量名),子类中不能重写
3. ordinal:返回当前对象的位置号,默认从0开始
4. values:返回当前枚举类中所有的常量
5. valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常!
6. compareTo:比较两个枚举常量,比较的就是位置号!
package com.dxl.staticpar;
public class EnumMethod {
public static void main(String[] args) {
Season2 autumn = Season2.AUTUMN;
System.out.println(autumn.name());
System.out.println(autumn.ordinal());//位置
Season2[] values = Season2.values();//返回一个数组,Season2[],含有定义的所有枚举对象
for (Season2 season : values){//增强for循环,遍历取出枚举数组
System.out.println(season);
}
// valueOf 先根据名称去查找,找到就返回,没找到就报错
Season2 autumn1 = Season2.valueOf("AUTUMN");
System.out.println("autumn1 = " + autumn1);
// 比较
/*
public final int compareTo(E o){
return self.ordinal - other.ordinal;
}
Season2.AUTUMN的编号[2- Season2.SUMMER的编号[3]
*/
System.out.println(Season2.AUTUMN.compareTo(Season2.SUNMMER));
// int[] nums = {1,5,6};
// System.out.println("=============普通for循环============");
// for (int i = 0;i < nums.length; i ++){
// System.out.println(nums[i]);
// }
// System.out.println("=============增强for循环=============");
// for (int i : nums){//依次从nums数组中取值付给i,没有值后就退出循环
// System.out.println("i = " + i);
// }
}
}
案例:
package com.dxl.staticpar;
public class Enumweration {
public static void main(String[] args){
Week[] weeks = Week.values();
for (Week i : weeks){
System.out.println(i);
}
}
}
enum Week{
MONDAY("星期一"),TUESDAY("星期二"), WEDNESDAY("星期三"),THURSDAY("星期四"),
FRIDAY("星期五"),SATURDAY("星期六"), SUNDAY("星期日");
private String name;
Week(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
enum实现接口
1)使用enum关键字后,就不能再继承其它类了,因为enum会隐式继承Enum,而Java是单继承机制。
2)枚举类和普通类一样,可以实现接口,如下形式。
enum 类名 implements 接口1,接口2{ }
package com.dxl.staticpar;
public class Enumweration {
public static void main(String[] args) {
Music.CLASSMUSIC.playing();
}
}
class A{
}
//enum Season extends A {//错误
//
//}
interface IPlaying{
public void playing();
}
enum Music implements IPlaying{
CLASSMUSIC;
@Override
public void playing() {
System.out.println("播放好听的音乐!");
}
}
注解的理解
1)注解(Annotation)也被称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。
2)和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
3)在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替java EE旧版中所遗留的繁冗代码和XML配置等。
基本的Annotation介绍
使用Annotation时要在其前面增加@符号,并把该Annotation当成一个修饰符使用。用于修饰它支持的程序元素
三个基本的Annotation:
1)@Override:限定某个方法,是重写父类方法,该注解只能用于方法2)@Deprecated:用于表示某个程序元素(类,方法等)已过时
3)@SuppressWarnings:抑制编译器警告
补充说明:@interface的说明
interface不是interface,是注解类是jdk5.0之后加入的
Override使用说明
1.@Override表示指定重写父类的方法(从编译层面验证),如果父类没有fly方法,则会报错
2.如果不写@Override注解,而父类仍有public void fly(){},仍然构成重写3.@Override只能修饰方法,不能修饰其它类,包,属性等等
4.查看@Override注解源码为@Target(ElementType.METHOD),说明只能修饰方法
5.@Target是修饰注解的注解,称为元注解
Deprecated的说明
1.用于表示某个程序元素(类,方法等)已过时
2.可以修饰方法,类,字段,包,参数等等
3.@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER, TYPE))
4.@Deprecated的作用可以做到新旧版本的兼容和过渡
package com.dxl.staticpar;
public class Deprecated_ {
public static void main(String[] args) {
A a = new A();
}
}
@Deprecated //类已过时,但是过时不代表不能用;即不推荐使用,但还是可以使用
class A {
public int n1 = 10;
public void hi(){
}
}
基本的 Annotation应用案例
@SuppressWarnings注解的案例
- unchecked是忽略没有检查的警告
- rawtypes是忽略没有指定泛型的警告(传参时没有指定泛型的警告错误)
3)unused是忽略没有使用某个变量的警告错误 - @SuppressWarnings 可以修饰的程序元素为,查看@Target
5)生成@SupperssWarnings时,不用背,直接点击左侧的黄色提示,就
可以选择(注意可以指定生成的位置)
package com.dxl.staticpar;
import java.util.ArrayList;
@SuppressWarnings({"all"})//大括号中写上需要抑制的警告类型
public class SuppressWarnings_ {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("tom");
arrayList.add("mary");
int i;
System.out.println(arrayList.get(1));
}
}
元注解的基本介绍
JDK的元Annotation 用于修饰其他Annotation
元注解:本身作用不大
元注解的种类(使用不多,了解,不用深入研究)
- Retention//指定注解的作用范围,三种SOURCE,CLASS,RUNTIME
- Target//指定注解可以在哪些地方使用
- Documented//指定该注解是否会在javadoc体现
- Inherited //子类会继承父类注解
Retention注解
说明
只能用于修饰一个 Annotation定义,用于指定该 Annotation可以保留多长时间,@Rentention包含一个 RetentionPolicy类型的成员变量,使用@Rentention时必须为该value成员变量指定值:
@Retention的三种值
- RetentionPolicy.SOURCE:编译器使用后,直接丢弃这种策略的注释
- RetentionPolicy.CLASS:编译器将把注释记录在class文件中.当运行Java程序时,JVM不会保留注解。这是默认值
- RetentionPolicy.RUNTIME:编译器将把注解记录在class文件中.当运行
Java程序时,JVM会保留注解.程序可以通过反射获取该注解
@Target 基本说明
用于修饰Annotation定义,用于指定被修饰的 Annotation能用于修饰哪些程序元素.@Target也包含一个名为value的成员变量。
@Documented 基本说明
@Documented:用于指定被该元 Annotation修饰的Annotation类将被javadoc工具提取成文档,即在生成文档时,可以看到该注解。
说明:定义为Documented的注解必须设置Retention值为RUNTIME。
@Inherited注解
被它修饰的Annotation将具有继承性.如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解
说明:实际应用中,使用较少,了解即可。
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
}
}
class Frock{
private static int currentNum = 10000;
private int serialNUmber;
public Frock(){
serialNUmber = getNextNum();
}
public static int getNextNum(){
currentNum +=100;
return currentNum;
}
public int getSerialNUmber() {
return serialNUmber;
}
}
class TestFrock{
public static void main(String[] args) {
System.out.println(Frock.getNextNum());
System.out.println(Frock.getNextNum());
Frock frock = new Frock();
Frock frock1 = new Frock();
Frock frock2 = new Frock();
System.out.println(frock.getSerialNUmber());
System.out.println(frock1.getSerialNUmber());
System.out.println(frock2.getSerialNUmber());
}
}
package com.dxl.staticpar;
public class Animal {
public static void main(String[] args) {
Animals animals = new Cat();
Animals animals1 = new Dog();
animals.shout();
animals1.shout();
}
}
abstract class Animals{
public abstract void shout();
}
class Cat extends Animals{
@Override
public void shout() {
System.out.println("猫会喵喵叫=====");
}
}
class Dog extends Animals{
@Override
public void shout() {
System.out.println("狗会汪汪叫=======");
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
cellPhone cellPhone = new cellPhone();
cellPhone.testWork(new ICalculate() {
@Override
public double work(double n1, double n2) {
return n1 + n2;
}
},12,56);
}
}
interface ICalculate{
public double work(double n1, double n2);
}
class cellPhone{
public void testWork(ICalculate iCalculate,double n1,double n2){
double result = iCalculate.work(n1,n2);
System.out.println("计算后的结果是: " + result);
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
A a = new A();
a.f1();
}
}
class A{
private String name = "hello";
public void f1(){
class B{
private String name = "hjj";
private final String NAME = "yiyi";
public void show(){
System.out.println("NAME= " + NAME + " name = " + name + " 外部类哒name = " + A.this.name);
}
}
B b = new B();
b.show();
}
}
案例:
package com.dxl.staticpar;
public interface Vehicles {
public void work();
}
package com.dxl.staticpar;
public class Horse implements Vehicles{
@Override
public void work() {
System.out.println("使用马作为交通工具===========");
}
}
package com.dxl.staticpar;
public class Boat implements Vehicles{
@Override
public void work() {
System.out.println("过河的时候使用小船===========");
}
}
package com.dxl.staticpar;
public class Plane implements Vehicles{
@Override
public void work() {
System.out.println("过火焰山使用飞机=========");
}
}
package com.dxl.staticpar;
public class VechiclesFactory {
private static Horse horse = new Horse();
private VechiclesFactory() {
}
public static Horse getHorse(){
// 马儿始终是同一匹马,使用饿汉式模式
// return new Horse();
return horse;
}
public static Boat getBoat(){
return new Boat();
}
public static Plane getPlane(){
return new Plane();
}
}
package com.dxl.staticpar;
public class Person {
private String name;
private Vehicles vehicles;
public Person(String name, Vehicles vehicles) {
this.name = name;
this.vehicles = vehicles;
}
public void passRiver(){
// Boat boat = VechiclesFactory.getBoat();
// boat.work();
if (!(vehicles instanceof Boat)){
vehicles = VechiclesFactory.getBoat();
}
vehicles.work();
}
public void common(){
if (!(vehicles instanceof Horse)) {
// 多态,向上转型
vehicles = VechiclesFactory.getHorse();
}
vehicles.work();
}
public void passMountain(){
if (!(vehicles instanceof Plane)){
vehicles = VechiclesFactory.getPlane();
}
vehicles.work();
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
Person person = new Person("唐僧", new Horse());
person.common();
person.passRiver();
person.passMountain();
}
}
成员内部类
package com.dxl.staticpar;
public class Homwork {
public static void main(String[] args) {
Car car = new Car(60);
car.getAir().flow();
}
}
class Car{
private double temperature;
public Car(double temperature) {
this.temperature = temperature;
}
class Air{
public void flow(){
if (temperature > 40){
System.out.println("温度大于40,空调吹冷气!");
}else if (temperature < 0){
System.out.println("温度小于0,空调吹暖气!");
}else{
System.out.println("正常温度,关闭空调!");
}
}
}
public Air getAir(){
return new Air();
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
Color black =Color.BLACK;
black.show();
//switch后放入枚举对象,在case后放入枚举对象就行
switch (black){
case BLACK:
System.out.println("匹配到黑色!");
break;
case RED:
System.out.println("匹配到红色");
break;
case BLUE:
System.out.println("匹配到蓝色");
break;
case GREEN:
System.out.println("匹配到绿色");
break;
case YELLOW:
System.out.println("匹配到黄色");
break;
default:
System.out.println("没有匹配到颜色");
}
}
}
interface IMYInterface{
public void show();
}
enum Color implements IMYInterface{
RED(255,0,0),
BLUE(0,0,255),
BLACK(0,0,0),
YELLOW(255,255,0),
GREEN(0,255,0);
private int redValue;
private int greenValue;
private int blueValue;
Color(int redValue, int greenValue, int blueValue) {
this.redValue = redValue;
this.greenValue = greenValue;
this.blueValue = blueValue;
}
@Override
public void show() {
System.out.println("属性值为 " + redValue + "," + greenValue + "," + blueValue);
}
}
异常处理机制:
package com.dxl.staticpar;
import java.lang.Exception;
public class Exception01 {
public static void main(String[] args) {
int num2 = 0;
int num1 = 23;
try {
int res = num1 / num2;
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("程序继续执行!");
}
}
异常介绍。
●基本概念
Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)
执行过程中所发生的异常事件可分为两类
- Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError[栈溢出]和OOM(out of
memory).Error是严重错误,程序会崩溃。 - Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:运行时异常和编译时异常门。
类的异常体系图
异常体系图一览
异常体系图的小结
1.异常分为两大类,运行时异常和编译时异常
2.运行时异常,编译器不要求强制处置的异常。一般是指编程时的
程序员应该避免其出现的异常。Java.lang.RununeExcepio都是运行时异常
3.对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理会对程序的可读性和运行效率产生影响
4.编译时异常,是编译器要求必须处置的异常。
常见的运行时异常
●常见的运行时异常包括
- NullPointerException空指针异常
- ArithmeticException数学运算异常
- ArraylndexOutOfBoundsException数组下标越界异常
- ClassCastException类型转换异常
- NumberFormatException数字格式不正确异常
编译异常
介绍
编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。
常见的编译异常
SQLException//操作数据库时,查询表可能发生异常
IOException//操作文件时,发生的异常
FileNotFoundException //当操作一个不存在的文件时,发生异常
ClassNotFoundException//加载类,而该类不存在时,异常
EOFException/操作文件,到文件未尾,发生异常
lllegalArguementException//参数异常
异常处理
●基本介绍
异常处理就是当异常发生时,对异常处理的方式。
●异常处理的方式
- try-catch-finally
程序员在代码中捕获发生的异常,自行处理 - throws
将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM
package com.dxl.staticpar;
public class Exception02 {
public static void main(String[] args) {
try {
String name = null;
System.out.println(name.length());
} catch (Exception e) {
e.printStackTrace();
}
}
}
try-catch异常处理
try-catch方式处理异常说明
1)Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try…catch块。
2)基本语法
try {
//可疑代码
1/将异常生成对应的异常对象,传递给catch块}
catch(异常){
//对异常的处理}
1/如果没有finally,语法可以通过
1)如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块.
2)如果异常没有发生,则顺序执行try的代码块,不会进入到catch.
3)如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码- finally {}
4)可以有多个catch语句,捕获不同的异常(进行不同的业务处里),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch。
package com.dxl.staticpar;
public class Exception02 {
public static void main(String[] args) {
try {
Person person = new Person();
person = null;
System.out.println(person.getName());
int n1 = 10;
int n2 = 0;
int res = n1/n2;
}catch (NullPointerException e){
System.out.println(e.getMessage());
}catch (ArithmeticException e){
System.out.println(e.getMessage());
}
catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
class Person{
private String name = "jaxk";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5)可以进行try-finally 配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉。应用场景,执行某段代码,不管是否发生异常,都要执行某个操作。
try {
//代码…}
finallyi1/总是执行}
try-catch异常处理
try-catch-finally执行顺序小结
1)如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally,最后还需要执行finally里面的语句
2)如果出现异常,则try块中异常发生后,try块剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句!
package com.dxl.staticpar;
import java.util.Scanner;
public class Exception02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while(true){
System.out.println("请输入一个整数:");
inputStr = scanner.next();
try {
num = Integer.parseInt(inputStr);
break;
} catch (NumberFormatException e) {
System.out.println("你输入的不是一个整数!");
}
}
System.out.println("输入的值是 num = " + num);
}
}
throws异常处理
基本介绍
1)如果一个方法((中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
2)在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异
常类型可以是方法中产生的异常类型,也可以是它的父类。
public void f2() throws FileNotFoundException,NullPointerException, ArithmeticException i
//创建了一个文件流对象
//1.这里的异常是一个FileNotFoundException 编译异常//2.使用前面讲过的try-catch-finally
//3.使用throws ,抛出异常,让调用f2方法的调用者(方法)处理
/ /4. throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类//5. throws 关键字后也可以是异常列表,即可以抛出多个异潮|
FileInputStream fis = new FileInputStream(“d: //aa.txt”);
}
throwS异常处理
·注意事项和使用细节
1)对于编译异常,程序中必须处理,比如try-catch 或者throws
2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理[举例]
3)子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型4)在throws 过程中,如果有方法 try-catch,就相当于处理异常,就可以不必
throws
public static void f4() {
//1.在f4()中调用方法f5()是OK/ /2.原因是f5()抛出的是运行异常
//3.而java中,并不要求程序员显示处理,因为有默认处理机制f5O);
}
public static void f5() throws ArithmeticException {
}
自定义异常
●基本概念
当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。
自定义异常的步骤
1)定义类:自定义异常类名(程序员自己写)继承Exception或RuntimeException
2)如果继承Exception,属于编译异常
3)如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)
package com.dxl.staticpar;
public class CustomException {
public static void main(String[] args) {
int age = 880;
if (!(age <= 80 && age >= 18)){
throw new AgeException("年龄需要在18-80");
}
System.out.println("你的年龄范围正确!");
}
}
//自定义的异常
class AgeException extends RuntimeException{
public AgeException(String message) {
super(message);
}
}
//1.一般情况下,我们白定义异常是继承RuntimeException
//2,即把自定义异常做成运行时异常,好处时,我们可以使用默认的处理机制
package com.dxl.staticpar;
public class CustomException {
public static void main(String[] args) {
try {
if (args.length != 2){
throw new ArrayIndexOutOfBoundsException("参数个数不对");
}
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
double res = cal(n1,n2);
System.out.println("计算结果是 res = " + res);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}catch (NumberFormatException e){
System.out.println("参数不是整数!");
}catch (ArithmeticException e){
System.out.println("出现除0的异常!");
}
}
public static double cal(int n1, int n2){
return n1/n2;
}
}
包装类
·包装类的分类 Wrapper
1.针对八种基本数据类型相应的引用类型包装类
2.有了类的特点,就可以调用类中的方法。
包装类
·包装类和基本数据的转换
演示包装类和基本数据类型的相互转换,这里以int和 Integer演示。
- jdk5前的手动装箱和拆箱方式,装箱:基本类型->包装类型,反之,拆箱
- jdk5 以后(含jdk5)的自动装箱和拆箱方式
3)自动装箱底层调用的是valueOf方法,比如lnteger.valueOf()
package com.dxl.staticpar;
public class WrapType {
public static void main(String[] args) {
// jdk5以前
int n1 = 100;
// 手动装箱
Integer integer = new Integer(n1);
Integer integer1 = Integer.valueOf(n1);
// 手动拆箱
int i = integer.intValue();
// jdk5以后自动装箱和拆箱
int n2 = 200;
// 底层调用的valueOf方法
Integer integer2 = n2;
int n3 = integer2;
}
}
package com.dxl.staticpar;
public class WrapperVSString {
public static void main(String[] args) {
// 包装类==》String
Integer i = 100;
// 方式1
String str1 = i + "";
// 方式2
String s = i.toString();
// 方式3
String s1 = String.valueOf(i);
// String==>包装类
// 方式1
String str4 = "123456";
Integer i1 = Integer.parseInt(str4);
// 方式2
Integer integer = new Integer(str4);
}
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
String类
String类的理解和创建对象
- String对象用于保存字符串,也就是一组字符序列
2)字符串常量对象是用双引号括起的字符序列。例如:“你好"、“12.97”."boy"等。
3)字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占杯个字节。 - String类较常用构造器(其它看手册):
String s1 = new String0;1/
String s2 = new String(String original);
String s3 = new String(chara);
String s4 = new String(char[] a,int startlndex,int count)·
说明:
package com.dxl.staticpar;
public class String_ {
public static void main(String[] args) {
String name = "jack";
name = "fjj";
final char[] value = {'a','b','c'};
char[] v = {'f','l','e'};
value[0] = 'l';
// value = v;不可以,不能修改value的地址
}
}
String类
两种创建String对象的区别
方式一:直接赋值 String s =“hhuu”;
方式二:调用构造器 String s2 = new String(“hhuu”);
1.方式一:先从常量池查看是否有"hhuu”数据空间,如果有,直接指向;如果
没有则重新创建,然后指向。S最终指向的是常量池的空间地址
2.方式二:先在堆中创建空间,里面维护了value属性,指向常量池的hsp空间。如果常量池没有"hhuu",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
- String是一个final类,代表不可变的字符序列
2)字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的.
String类的常见方法
●说明
String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此java设计者还提供了StringBuilder和 StringBuffer来增强String的功能。并提高效率。
StringBuilder 和StringBuffer]
String s = new String(“”);
for( int i = 0; i< 80000; i++){
S+=“hello”;
}
String类的常见方法
String类的常见方法应用实例1
equals //区分大小写,判断内容是否相等
equalslgnoreCase//忽略大小写的判断内容是否相等
length/获取字符的个数,字符串的长度
indexOf//获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
lastIndexOf //获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
substring //截取指定范围的子串
trim//去前后空格
charAt:获取某索引处的字符,注意不能使用Str[index]这种方式.
String str = "hello” ;
//str[0]不对
//str.charAt(O)=>h
package com.dxl.staticpar;
public class String_ {
public static void main(String[] args) {
// 1.equals 区分大小写,比较内容是否相同
String str1 = "hello";
String str2 = "Hello";
System.out.println(str1.equals(str2));
// 2.equalsIgnoreCase 忽略大小写判断内容是否相同
String username = "john";
if("john".equalsIgnoreCase(username)){
System.out.println("Success");
}else{
System.out.println("Fail");
}
// 3.length 获取字符的个数,字符串的长度
System.out.println("呀呀呀".length());
// 4.index0f 获取字符在字符串对象中第一次出现的索引,索引从0开始,如果找不到,返回-1
String s1 = "hdfjjf$jfkk";
int index = s1.indexOf('$');
System.out.println(index);
// 5.lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从0开始,如果找不到,返回-1
s1 = "jfdjhhfa@@@jjk@";
index = s1.lastIndexOf('@');
System.out.println(index);
// 6.substring截取指定范围的子串
String name = "hello,张三";
System.out.println(name.substring(6));
System.out.println(name.substring(0,3));
}
}
String类的常见方法
String类的常见方法应用实例2
第二组String相关的方法:
toUpperCase
toLowerCase
concat
replace 替换字符串中的字符
split分割字符串,对于某些分割字符,我们需要转义比如|等
compareTp //比较两个字符串的大小
toCharArray //转换成字符数组
format //格式字符串,%s字符串%c字符%d整型%.2f 浮点型
package com.dxl.staticpar;
public class String_ {
public static void main(String[] args) {
// 1.toUpperCase 转换成大写
String s = "hoLLo";
System.out.println(s.toUpperCase() );
// 2.toLowerCase
System.out.println(s.toLowerCase());
// 3.concat拼接字符串
String s1 = "宝玉";
s1 = s1.concat("林黛玉").concat("薛宝钗").concat("一起");
System.out.println(s1);
// 4.replace 替换字符串中的字符
s1 = "hahhahhyyuutey";
String s11 = s1.replace('h','o');
System.out.println(s11);
System.out.println(s1);//本身s1是不会变的
// 5.split 分割字符串,对于某些分割字符,我们需要转移| \\等
String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";
String[] split = poem.split(",");
poem = "E:\\aaa\\bbb";
//在对字符串进行分割时,如果有特殊字符,需要加入转义字符\
split = poem.split("\\\\");
for (int i = 0; i < split.length;i ++){
System.out.println(split[i]);
}
// 6.toCharArray 转成字符数组
s = "happy";
char[] chs = s.toCharArray();
for (int i = 0 ; i < chs.length; i ++){
System.out.println(chs[i]);
}
// 7.compareTo 比较两个字符串的大小,如果前者大,则返回正数,后者大,则返回负数,如果相等,返回0
// (1)如果长度相同,并且每个字符也相同,就返回0
// (2)如果长度相同或者不相同,但是在进行比较时,可以区分大小
// 就返回 if (c1 != c2){
// return c1 - c2;
// }
// (3)如果前面的部分都相同,就返回 str1.len - str2.len
String a = "jchn";
String b = "jack";
System.out.println(a.compareTo(b));//'c' - 'a' = 2
// 8.format格式字符串
// %S字符串%c字符%d整型%.2f 浮点型
String name = "john";
int age = 10;
double score = 93.3/3;
char gender = '男';
String info = "我的名字:" + name + "年龄:" + age + "成绩:" + score + "性别: " + gender;
info = String.format("我的名字:%s年龄:%d成绩:%.2f性别: %c",name,age,score,gender);
System.out.println(info);
}
}
StringButter类
●基本介绍·
StringBuffer01.java
java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。很多方法与String相同,但StringBuffer是可变长度的。
String Buffer是一个容器。
//1.StringBuffer的直接父类是 AbstractStringBuilder
//2. StringBuffer实现了 Serializable,即StringBuffer的对象可以串行化
//3.在父类中 AbstractStringBuilder有属性 char[] value,不是final,该value 数组存放字符串内容,引出存放在堆中的
//4. StringBuffer是一个 final类,不能被继承
//5.因为StringBuffer字符内容是存在 char[] value,所有在变化(增加/删除)l/ 不用每次都更换地址(即不是每次创建新对象),所以效率高于String
String VS StringBuffer
- String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低//private final char value[];
- StringBuffer保存的是字符串变量,里面的值可以更改,每次
StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高
//char[] value;//这个放在堆.
String和StringBuffer之间的相互转换
package com.dxl.staticpar;
public class StringBuffer01 {
public static void main(String[] args) {
// String转成StringBuffer
String str = "hello tom";
// 方式一
// 返回的才是StringBuffer对象,对str本身没有影响
StringBuffer stringBuffer = new StringBuffer(str);
// 方式二
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str);
// StringBuffer ==》 String
StringBuffer ainaini = new StringBuffer("ainaini");
// 方式一:使用提供的toString方法
String s = ainaini.toString();
// 方式二:
String s1 = new String(ainaini);
}
}
StringBuffer类常见方法
1)增append
2)delete(start,end)
3)改replace(start,end,string)//将
start----end间的内容替换掉,不含end
4)查indexOf //查找子串在字符串第1
次出现的索引,如果找不到返回-1
5)插insert
6)获取长度length
package com.dxl.staticpar;
public class StringBuffer01 {
public static void main(String[] args) {
String price = "12345689.59";
StringBuffer sb = new StringBuffer(price);
for (int i = sb.lastIndexOf(".") - 3; i >0; i -= 3){
sb = sb.insert(i, ",");
}
System.out.println(sb);
}
}
StringBuilder类
基本介绍
1)一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同
步。(StringBuilder不是线程安全的)该类被设计用作 StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer 要快。
2)在 StringBuilder上的主要操作是 append和insert方法,可重载这些方法,以接受任意类型的数据。
StringBuilder常用方法
StringBuilder 和 StringBuffer均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样.
1.StringBuilder是final,不能被继承
2.继承了AbstractStringBuilder,属性char[] value,内容存到value
3.实现了Serializable接口,序列化(所谓序列化即可以保存类型和数据本身)
String、StringBuffer 和StringBuilder的比较
- StringBuilder和 StringBuffer非常类似,均代表可变的字符序列,而且方法也一样
- String:不可变字符序列,效率低,但是复用率高。
- StringBuffer:可变字符序列、效率较高(增删)、线程安全,看源码4)StringBuilder:可变字符序列、效率最高、线程不安全
- String使用注意说明:
string s=“a”; 1/创建了一个字符串
s += “b”;//实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+“b”(也就是"ab”)。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能=>结论:如果我们对String做大量修改,不要使用String
package com.dxl.staticpar;
public class StringBuffer01 {
public static void main(String[] args) {
long startTime = 0L;
long endTime = 0L;
StringBuffer stringBuffer = new StringBuffer("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
stringBuffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
StringBuilder stringBuilder = new StringBuilder("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
stringBuilder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
String text = "";
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
}
效率:StringBuilder > StringBuffer > String
String、StringBuffer 和StringBuilder的选择
使用的原则
1.如果字符串存在大量的修改操作,一般使用 StringBuffer 或StringBuilder
2.如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder
3.如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer
4.如果我们字符串很少修改,被多个对象引用,使用String.比如配置信息等StringBuilder 的方法使用和 StringBuffer 一样,不再说.
Math类
●基本介绍
Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
Arrays类
●Arrays类常见方法应用案例
Arrays里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)。1) toString返回数组的字符串形式
Arrays.toString(arr)
2) sort排序(自然排序和定制排序)Integer arr[l] ={1, -1,7,0,89];3) 3)binarySearch 通过二分搜索法进行查找,要求必须排好序
int index = Arrays.binarySearch(arr, 3);
4) copyOf 数组元素的复制
lnteger[] newArr = Arrays.copyOf(arr, arr.length);
5) fill 数组元素的填充
Integer[] num = new Integer[1{9,3,23;Arrays.fill(num, 99);
6) equals 比较两个数组元素内容是否完全一致boolean equals = Arrays.equals(arr, arr2);
7)asList 将一组值,转换成list
List asList = Arrays.asList(2,3,4.5.6,1);System.out.println(“asList=” + asList);
package com.dxl.staticpar;
import java.util.Arrays;
import java.util.Comparator;
public class StringBuffer01 {
public static void main(String[] args) {
Integer[] integers = {1,2,5};
// for (int i = 0; i < integers.length; i++) {
// System.out.println(integers[i]);
// }
// 直接使用toString来显示数组信息
// System.out.println(Arrays.toString(integers));
// sort的使用
//1.可以直接使用冒泡排序,也可以直接使用Arrays提供的sort方法排序
// 2.因为数组是引用类型,所以通过sort排序后,会直接影响到实参arr
// 3. sort重载的,也可以通过传入一个接口 Comparator实现定制排序
//4.调用定制排序时,传入两个参数〔1)排序的数组 arr
//(2)实现了Comparator接口的匿名内部类,要求实现compare方法
//接口编程
Integer arr[] = {1,-1,4,5,0,89};
// Arrays.sort(arr);默认排序
// 定制排序
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2
return i2 - i1;
}
});
System.out.println("================");
System.out.println(Arrays.toString(arr));
}
}
package com.dxl.staticpar;
import java.util.Comparator;
public class StringBuffer01 {
public static void main(String[] args) {
int[] arr = {1, -1,2 ,8 ,36};
bubble02(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
int i1 = (Integer)o1;
int i2 = (Integer)o2;
return i2 - i1;
}
});
}
// 冒泡 + 定制
public static void bubble02(int[] arr, Comparator c){
int temp = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length-1 - i; j++) {
if (c.compare(arr[j],arr[j + 1] )> 0){
temp = arr[j];
arr[j ] = arr[j+1];
arr[j + 1] = temp;
}
}
}
}
}
package com.dxl.staticpar;
import java.util.Arrays;
import java.util.List;
public class StringBuffer01 {
public static void main(String[] args) {
int[] arr = {1, -1, 2, 8, 36};
// 二分查找要求数组是有序的
//1.使用 binarySearch二叉查找
//2.要求该数组是有序的。如果该数组是无序的,不能使用binarySearch
//3.如果数组中不存在该元素,就返回return -(low + 1);
// key not found.
int index = Arrays.binarySearch(arr,1);
System.out.println("index = "+index);
// 数组复制
//1.从 arr数组中,拷贝 arr.length个元素到newArr数组中
// 2.如果拷贝的长度> arr.length就在新数组的后面增加l null
// 3.如果拷贝长度<0就抛出异常NegativeArraySizeException
// 4。该方法的底层使用的是 System. arraycopy )
int[] newArr =Arrays.copyOf(arr,arr.length + 1);
System.out.println(Arrays.toString(newArr));
//1.使用99去填充num数组,可以理解成是替换原理的元素
Integer[] num = new Integer[]{8,9,5};
Arrays.fill(num,99);
System.out.println(Arrays.toString(num));
//1.如果arr和 arr2数组的元素一样,则方法true;
// 2.如果不是完全一样,就返回 false
Integer[] arr2 = new Integer[]{5,8,9};
Integer[] arr1 = new Integer[]{5,8,9};
boolean equals = Arrays.equals(arr1, arr2);
System.out.println( "equals=" +equals);
//1. asList方法,会将〔2,3,4,5,6,1)数据转成一个List集合
// 2.返回的 asList 编译类型 List(接口)
//3. asList运行类型java.util.Arrays#ArrayList,是Arrays类的
//静态内部类 private static class ArrayList<E>
// extends AbstractList<E>
//implements RandomAccess, java.io.Serializable
List asList = Arrays.asList(2,3,4,5,6,1);
System.out.println("asList=" + asList);
System.out.println("asList的运行类型" +asList.getClass());
}
}
package com.dxl.staticpar;
import java.util.Arrays;
import java.util.Comparator;
public class ArrayExercise {
public static void main(String[] args) {
Book[] books = new Book[4];
books[0] = new Book("红楼梦",100);
books[1] = new Book("金瓶梅新",90);
books[2] = new Book("青年文摘20年",5);
books[3] = new Book("java",20);
// 价格从小到大
// Arrays.sort(books, new Comparator() {
// @Override
// public int compare(Object o1, Object o2) {
// Book book1 = (Book)o1;
// Book book2 = (Book) o2;
// double priceVal = book2.getPrice() - book1.getPrice();
// if (priceVal > 0){
// return -1;
// }else if(priceVal < 0){
// return 1;
// }else{
// return 0;
// }
// }
// });
//书名长度排序
Arrays.sort(books, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Book book1 = (Book)o1;
Book book2 = (Book) o2;
return book1.getName().length() - book2.getName().length();
}
});
System.out.println(Arrays.toString(books));
}
}
class Book{
private String name;
private double price;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
System类
System类常见方法和案例
- exit退出当前程序
- arraycopy :复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组.
int[] src={1,2,3];
int[ dest = new int[3];
System.arraycopy(src, 0, dest, 0, 3); - currentTimeMillens:返回当前时间距离1970-1-1的毫秒数4) gc:运行垃圾回收机制System.gc(;
package com.dxl.staticpar;
import java.util.Arrays;
public class SystemEx {
public static void main(String[] args) {
// System.out.println("ok1");
// System.exit(0);//0表示正常退出的值
// System.out.println("ok2");
int[] src = {1,2,5};
int[] test = new int[3];
System.arraycopy(src,0,test,0,src.length);
System.out.println(test[0] +"" + test[1] + test[2]);
System.out.println("test=" + Arrays.toString(test));
System.out.println(System.currentTimeMillis());
}
}
Biglnteger和BigDecimal类
Biglnteger和BigDecimal常见方法
- add 加
- subtract减
- multiply乘
- divide除
Biglnteger和BigDecimal类
Biglnteger和BigDecimal介绍
应用场景: - Biglnteger适合保存比较大的整型
- BigDecimal适合保存精度更高的浮点型(小数)
package com.dxl.staticpar;
import java.math.BigDecimal;
import java.math.BigInteger;
public class SystemEx {
public static void main(String[] args) {
BigInteger bigInteger = new BigInteger("145555555555551587456654");
BigInteger bigInteger1 = new BigInteger("100");
System.out.println(bigInteger);
BigInteger add = bigInteger.add(bigInteger1);
System.out.println(add);
// 减
BigInteger substract = bigInteger.subtract(bigInteger1);
System.out.println(substract);
BigDecimal bigDecimal = new BigDecimal("48512.524785654478562145631278893652234557856622");
BigDecimal bigDecimal1 = new BigDecimal("125.654");
System.out.println(bigDecimal.add(bigDecimal1));
System.out.println(bigDecimal.divide(bigDecimal1,BigDecimal.ROUND_CEILING));//除法可能抛异常,除不尽
}
}
第一代日期类
- Date:精确到毫秒,代表特定的瞬间
- SimpleDateFormat:格式和解析日期的类
SimpleDateFormat格式化和解析日期的具体类。它允许进行格式化(日期->文本)、解析(文本->日期)和规范化.
package com.dxl.staticpar;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SystemEx {
public static void main(String[] args) throws ParseException {
Date date = new Date();
System.out.println("当前日期= " + date);
Date date1 = new Date(1248766656);
System.out.println(date1.getTime());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
String format = simpleDateFormat.format(date);
System.out.println(format);
String s = "2022年07月10日 05:19:12 星期日";
Date parse = simpleDateFormat.parse(s);
System.out.println(parse);
System.out.println("parse=" + simpleDateFormat.format(parse));
}
}
日期类。
第二代日期类
1)第二代日期类,主要就是Calendar类(日历)。
public abstract class Calendar extends Object implements Serializable,Cloneable, Comparable
2) Calendar类是一个抽象类,它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR 等白历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
package com.dxl.staticpar;
import java.util.Calendar;
public class SystemEx {
public static void main(String[] args) {
//1. Calendar是一个抽象类,并且构造器是private
// 2.可以通过 getInstance()来获取实例
//3.提供大量的方法和字段提供给程序员
//4. calendar没有提供对应的格式化的类,因此需要程序员自己组合来输出
//5.如果我们需要按照24小时进制来获取时间,Calendar . HOUR '==改成=> Calendar.HOUR_OF_DAYl
Calendar c = Calendar.getInstance();
System.out.println(c);
//2.获取日历对象的某个目历字段
System.out.println("年:" +c.get(Calendar. YEAR));
//这里为什么要 +1,因为Calendar返回月时候,是按照0开始编号
System.out.println("月:" + (c.get(Calendar. MONTH) +1));
System.out.println("日:" +c.get(Calendar.DAY_OF_MONTH));
System.out.println("小时:" +c.get(Calendar . HOUR));
System.out.println("小时:" +c.get(Calendar . HOUR_OF_DAY));
System.out.println("分钟:" +c.get(Calendar.MINUTE));
System.out.println("秒:" +c.get(Calendar . SECOND));
//Calender没有专门的格式化方法,所以需要程序员自己来组合显示
System.out.println(c.get(Calendar.YEAR) + "年");
}
}
日期类。
第三代日期类
前面两代日期类的不足分析
JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar也存在问题是:
1)可变性:像日期和时间这样的类应该是不可变的。
2)偏移性:Date中的年份是从1900开始的,而月份都从0开始。3)格式化:格式化只对Date有用,Calendar则不行。
4)此外,它们也不是线程安全的;不能处理闰秒等(每隔2天,多出1s)。
第三代日期类常见方法
-
LocalDate(日期/年月日)、LocalTime(时间/时分秒)、LocalDateTime(日期时电/年月日时分秒)JDK8加入
·LocalDate只包含日期,可以获取日期字段
LocalTime只包含时间,可以获取时间字段
LocalDateTime包含日期+时间,可以获取日期和时间字段:
LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()
System.out.println(ldt);
ldt.getYear();ldt.getMonthValue();ldt.getMonth();ldt.getDayOfMonth();
ldt.getHour();ldt.getMinute();ldt.getSecond(); -
DateTimeFormatter格式日期类类似于SimpleDateFormat
DateTimeFormat dtf = DateTimeFormatter.ofPattern(格式);
String str = dtf.format(日期对象);
案例演示:
LocalDateTime ldt = LocalDateTime.now0;
//关于DateTimeFormatter 的各个格式参数,需要看jdk8的文档.
DateTimeFormatter dtf = DateTimeFormatter. ofPattern(“yyy年MM月dd日HIHJT时mm分钟ss秒”);
String strDate = dtf.format(ldt);
package com.dxl.staticpar;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDate_ {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()
System.out.println(ldt);
System.out.println("年" + ldt.getYear());
ldt.getMonthValue();
ldt.getMonth();
System.out.println("月" + ldt.getMonthValue());
ldt.getDayOfMonth();
ldt.getHour();
ldt.getMinute();
ldt.getSecond();
LocalDate now = LocalDate.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月");
String format = dtf.format(ldt);
System.out.println(format);
}
}
- Instant时间戳类似于Date
提供了一系列和Date类转换的方式lnstant—->Date:
Date date = Date.from(instant);Date->lnstant:
lnstant instant = date.tolnstant(;案例演示:
lnstant now= Instant.nowO;System.out.println(now);Date date = Date.from(now);lnstant instant = date.tolnstant(;
package com.dxl.staticpar;
import java.time.Instant;
import java.util.Date;
public class LocalDate_ {
public static void main(String[] args) {
// 时间戳 通过静态方法now()获取表示当前时间戳的对象
Instant now = Instant.now();
System.out.println(now);
Date date = Date.from(now);//通过from方法转换成date
Instant instant = date.toInstant();//通过date的toInstant() 可以把 date转成Instant对象
}
}
4)第三代日期类更多方法- LocalDateTime类
MonthDay类:检查重复事件·是否是闰年
·增加日期的某个部分
·使用plus方法测试增加时间的某个部分
·使用minus方法测试查看一年前和一年后的日期
编程思想,写出对的情况然后取反
package com.dxl.staticpar;
public class Homework {
public static void main(String[] args) {
String str = "fekjfjkg";
try {
str = reverse(str,2,6);
} catch (Exception e) {
System.out.println(e.getMessage());
return;
}
System.out.println(str);
}
public static String reverse(String str, int start, int end){
if (!(str != null && start >= 0 && end <= str.length())){
throw new RuntimeException("参数不正确");
}
char[] chars = str.toCharArray();
char temp = ' ';
for (int i = start, j = end; i < j; i++, j--) {
temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
return new String(chars);
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
String name = "jack";
String pwd = "124452";
String email = "jack@sohu.com";
try {
userRegist(name,pwd,email);
System.out.println("恭喜你注册成功!");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void userRegist(String name,String pwd,String email){
if (!(name != null && pwd != null && email != null)){
throw new RuntimeException("恭喜你,注册成功!");
}
int userLength = name.length();
if (!(userLength >= 2 && userLength <= 4)){
throw new RuntimeException("用户名长度为2或3或4");
}
if (!(pwd.length() == 6 && isDigital(pwd))){
throw new RuntimeException("密码长度不对!");
}
int i = email.indexOf('@');
int j = email.indexOf('.');
if (!(i > 0 && j >i)){
throw new RuntimeException("邮箱中包含@!");
}
}
public static boolean isDigital(String str){
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] < '0' || chars[i] > '9'){
return false;
}
}
return true;
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args) {
String name = "Huan shun Ping";
printName(name);
}
public static void printName(String str){
if (str == null){
System.out.println("str 不能为空");
return;
}
String[] names = str.split(" ");
if (!(names.length == 3)){
System.out.println("输入的字符串格式不对!");
return;
}
System.out.println(String.format("%s,%s .%c",names[2],names[0],names[1].toUpperCase().charAt(0)));
}
}
package com.dxl.staticpar;
public class HomeWork {
public static void main(String[] args){
String str = "kjdfsjjgj PPJJ 154566";
countStr(str);
}
public static void countStr(String str){
if (str == null){
System.out.println("输入不能为空!");
return;
}
int strLen = str.length();
int numCount = 0;
int lowerCount = 0;
int upperCount = 0;
int otherCount = 0;
for (int i =0; i < strLen; i++){
if (str.charAt(i) >= '0' && str.charAt(i) <= '9'){
numCount ++;
}else if (str.charAt(i) >= 'a' && str.charAt(i) <= 'z'){
lowerCount ++;
}else if (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z'){
upperCount ++;
}else{
otherCount ++;
}
}
System.out.println("数字有:" + numCount);
System.out.println("小写字母有:" + lowerCount);
System.out.println("大写字母有:" + upperCount);
System.out.println("其他字符有:" + otherCount);
}
}
集合的理解和好处
前面我们保存多个数据使用的是数组,那么数组有不足的地方。
●数组
1)长度开始时必须指定,而且一旦指定,不能更改
2)保存的必须为同一类型的元素
3)使用数组进行增加元素
Person[] pers = new Person[1];
pers[0]=new Person();
//增加新的Person对象?
Person[] pers2 = new Person[pers.length+1];//新创建数组
for(){}//拷贝pers数组的元素到pers2
pers2[pers2.length-1]=new Person()😕/添加新的对象
●集合
1)可以动态保存任意多个对象,使用比较方便!
2)提供了一系列方便的操作对象的方法:add、remove、set、 get等
3)使用集合添加删除新元素的示意代码-简洁了
集合的框架体系
Java的集合类很多,主要分为两大类,如图:
//1.集合主要是两组(单列集合,双列集合)
//2. Collection接口有两个重要的子接口 List Set,他们的实现子类都是单列集合
//3. Map接口的实现子类是双列集合,存放的 K-V
Collection接口和常用方法
●Collection接口实现类的特点
public interface Collection extends Iterable
1)collection实现子类可以存放多个元素,每个元素可以是Object
2)有些Collection的实现类,可以存放重复的元素,有些不可以
3)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
4) Collection接口没有直接的实现子类,是通过它的子接口Set 和 List来实现的
Collection接口常用方法,以实现子类ArrayList
- add:添加单个元素
2)remove:删除指定元素 - contains:查找元素是否存在
- size:获取元素个数
- isEmpty:判断是否为空
- clear:清空
- addAll:添加多个元素
- containsAll:查找多个元素是否都存在
- removeAll:删除多个元素
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.HashMap;
public class Collwction_ {
@SuppressWarnings({"all"})
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("ton");
arrayList.add(true);
System.out.println("list= " + arrayList);
arrayList.remove(0);
System.out.println("list = " + arrayList);
arrayList.remove(true);
System.out.println("list= " + arrayList);
// contains:查找元素是否存在
System.out.println(arrayList.contains("jack"));
// size:获取元素个数
System.out.println(arrayList.size());
System.out.println(arrayList.isEmpty());
arrayList.clear();
System.out.println("list = " + arrayList);
ArrayList list = new ArrayList();
list.add("红楼梦");
list.add("三国演义");
arrayList.addAll(list);
System.out.println("arrayList = " + arrayList);
arrayList.add("聊斋志异");
arrayList.removeAll(list);
System.out.println("arrayList = " + arrayList);
HashMap hashMap = new HashMap();
hashMap.put("N01","北京");
}
}
Collection接口和常用方法
Collection接口遍历元素方式1-使用lterator(送代器)基本介绍
- Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
2)所有实现了Collection接口的集合类都有一个iterator()方法,用以返回
一个实现了lterator接口的对象,即可以返回一个迭代器。 - Iterator的结构.[图:]
- Iterator仅用于遍历集合,lterator本身并不存放对象。
迭代器的执行原理
lterator iterator = coll.iterator(0);1/得到一个集合的迭代器
//hasNext()判断是否还有下一个元素while(iterator.hasNext()){
/next(:①指针下移②将下移以后集合位置上的元素返回
System.out.println(iterator.next));}
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Collwction_ {
public static void main(String[] args) {
@SuppressWarnings({"all"})
Collection col = new ArrayList();
col.add(new Book("红楼梦","曹雪芹",6.54));
col.add(new Book("小李飞刀","古龙",23.2));
col.add(new Book("红楼梦","曹雪晴",15.3));
Iterator iterator = col.iterator();
while(iterator.hasNext()){
Object next = iterator.next();
System.out.println("next= " + next);
}
// 迭代器第二次重置
Iterator iterator1 = col.iterator();
while (iterator1.hasNext()) {
Object next = iterator1.next();
System.out.println("next= " + next);
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
Collection接口和常用方法
Collection接口遍历对象方式2-for循环增强.
增强for循环,可以代替iterator迭代器,特点:增强for就是简化版的iterator,本质一样。只能用于遮历集合或数组。
基本语法
for(元素类型元素名:集合名或数组名){
访问元素
}
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Collection;
public class Collwction_ {
public static void main(String[] args) {
@SuppressWarnings({"all"})
Collection col = new ArrayList();
col.add(new Book("红楼梦","曹雪芹",6.54));
col.add(new Book("小李飞刀","古龙",23.2));
col.add(new Book("红楼梦","曹雪晴",15.3));
// 增强for循环
for (Object book:col){
System.out.println("book= " +book);
}
//1.使用增强for,在Collection集合
// 2.增强for,底层仍然是迭代器
//3.增强for可以理解成简化版的迭代器
int[] nums = {1,8,5,10};
for (int i: nums){
System.out.println("i = " + i);
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Collwction_ {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Dog("小黑",5));
list.add(new Dog("小红",3));
list.add(new Dog("小明",6));
for (Object dog:list){
System.out.println("dog = " + dog);
}
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("dog = " + next);
}
}
}
class Dog{
private String name;
private int age;
public Dog(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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
List接口和常用方法
List接口基本介绍
List接口是 Collection 接口的子接口
- List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
- List集合中的每个元素都有其对应的顺序索引,即支持索引。
- List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
4)JDK API中List接口的实现类有:
常用的有:ArrayList、LinkedList和Vector。
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings({"all"})
public class List_ {
public static void main(String[] args) {
//1.List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
List list = new ArrayList();
list.add("jack");
list.add("tom");
list.add("jjhh");
list.add("mary");
System.out.println("list = " + list);
//2. List集合中的每个元素都有其对应的顺序索引,即支持索引
// 0bject get(int index):获取指定index位置的元素
System.out.println(list.get(2));
list.add(1,"jjdhe");
System.out.println("list = " + list);
List list1 = new ArrayList();
list1.add("张三丰");
list1.add("韩语");
list.addAll(1,list1);
System.out.println("list= " + list);
// int index0f(0bject obj):返回obj在集合中首次出现的位置
System.out.println(list.indexOf("tom"));
// int lastIndexOf(0bject obj):返回obj在当前集合中末次出现的位置
System.out.println(list.lastIndexOf("tom"));
// 0bject remove(int index):移除指定index位置的元素,并返回此元素
list.remove(0);
System.out.println("list = " + list);
// Object set(int index,0bject ele):设置指定index位置的元素为ele ,相当于是替换。
list.set(1, "玛丽");
System.out.println("list = " + list);
// List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合
List list2 = list.subList(0,2);
System.out.println("list2 = " + list2);
}
}
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@SuppressWarnings({"all"})
public class List_ {
public static void main(String[] args) {
List list = new ArrayList();
for (int i = 0; i < 12; i ++){
list.add("hello " + i);
}
System.out.println("list = " + list);
list.add(1,"jdjhd");
System.out.println("list = " + list);
System.out.println("第五个元素 = " + list.get(4));
list.remove(5);
System.out.println("list = " + list);
list.set(6,"三国演义");
System.out.println("list = " + list);
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("list = " + list);
}
}
}
package com.dxl.staticpar;
import java.util.LinkedList;
import java.util.List;
@SuppressWarnings({"all"})
public class List_ {
public static void main(String[] args) {
// List list = new ArrayList();
// List list = new Vector();
List list = new LinkedList();
list.add(new Book("红楼梦","曹雪芹",45.6));
list.add(new Book("西游记","吴承恩",12.3));
list.add(new Book("三国演义","罗贯中",15.6));
list.add(new Book("水浒传","施耐庵",45.78));
for(Object o: list){
System.out.println(o);
}
// 冒泡排序
sort(list);
System.out.println("=====排序后====");
for (Object o : list){
System.out.println(o);
}
}
// 对集合进行排序
public static void sort(List list){
for (int i = 0; i < list.size() - 1; i ++ ){
for (int j = 0; j < list.size() - 1 - i; j ++){
Book book1 = (Book) list.get(j);
Book book2 = (Book) list.get(j + 1);
if (book1.getPrice() > book2.getPrice()){
list.set(j, book2);
list.set(j+1,book1);
}
}
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "名称:" + name + '\t' +
"作者:" + author + '\t' +
"价格:" + price;
}
}
1)permits all elements, including null ,ArrayList可以加入nulL,并且多个
2) ArrayList是由数组来实现数据存储的
3)ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高),在多线程情况下,不建议使用ArrayList
package com.dxl.staticpar;
import java.util.ArrayList;
public class ArrayListDetail {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(null);
arrayList.add("jack");
System.out.println(arrayList);//[null, jack]
}
}
ArrayList底层结构和源码分析
- ArrayList中维护了一个Object类型的数组elementData.
transient Object[] elementData;
transient表示瞬间的,短暂的,该属性不会被序列化
2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
package com.dxl.staticpar;
import java.util.ArrayList;
public class ArrayListDetail {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
for (int i = 0; i <= 10; i++) {
arrayList.add(i);
}
for (int i = 10; i <= 20; i++) {
arrayList.add(i);
}
arrayList.add(null);
arrayList.add("jack");
System.out.println(arrayList);//[null, jack]
}
}
Vector底层结构和源码剖析
Vector的基本介绍
- Vector类的定义说明
- Vector底层也是一个对象数组protected Object[] elementData;
- Vector 是线程同步的,即线程安全, Vector类的操作方法带有synchronized
4)在开发中,需要线程同步安全时,考虑使用Vector
inkedList底层结构
LinkedList的全面说明
1)LinkedList底层实现了双向链表和双端队列特点
2)可以添加任意元素(元素可以重复),包括null
3)线程不安全,没有实现同步
LinkedList氐层结构
LinkedList的底层操作机制
- LinkedList底层维护了一个双向链专
- LinkedList中维护了两个属性first和last分别指向首节点和尾节点
3)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表
4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
package com.dxl.staticpar;
public class LinkList_ {
public static void main(String[] args) {
Node jack = new Node("jack");
Node tom = new Node("tom");
Node jhfe = new Node("jhfe");
//连接三个节点,行成双向列表;
jack.next = tom;
tom.next = jhfe;
jhfe.pre = tom;
tom.pre = jack;
Node first = jack;//第一个节点,头结点
Node last = jhfe;//最后一个节点,尾结点
//从头到尾进行遍历
while (true){
if (first == null){
break;
}
System.out.println(first);
first = first.next;
}
//从尾到头的遍历
while (true){
if (last == null){
break;
}
System.out.println(last);
last = last.pre;
}
// 添加一个Node节点
Node smith = new Node("Smith");
tom.next = smith;
smith.next = jhfe;
jhfe.pre = smith;
smith.pre = tom;
first = jack;
while (true){
if (first == null){
break;
}
System.out.println(first);
first = first.next;
}
}
}
//定义一个Node类,Node对象,表示双向链表的一个节点
class Node{
public Object item;//正在存放数据
public Node next;//后一个节点
public Node pre;//前一个节点
public Node(Object name){
this.item = name;
}
@Override
public String toString() {
return "Node name = " + item ;
}
}
删除
package com.dxl.staticpar;
import java.util.Iterator;
import java.util.LinkedList;
public class LinkList_ {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(5);
linkedList.add(1);
linkedList.add(7);
System.out.println("linkedList= " + linkedList);
linkedList.remove();//默认拿掉第一个
System.out.println("linkedList=" + linkedList);
linkedList.set(1,22222);
System.out.println("linkedList = " + linkedList);
Object o = linkedList.get(1);//获取双向链表的第2个对象
System.out.println(o);
//LinkedList实现了list接口,可以用迭代器遍历
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println("next = " + next);
}
for(Object o1 : linkedList){
System.out.println("linke = " + o1);
}
for (int i = 0; i < linkedList.size(); i ++){
System.out.println(linkedList.get(i));
}
}
}
如何选择ArrayList和LinkedList:
1)如果我们改查的操作多,选择ArrayList
2)如果我们增删的操作多,选择LinkedList
3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.
Set接口和常用方法
Set接口基本介绍
1)无家(添加和取出的顺序不一致),没有索引
2)不允许重复元素,所以最多包含一个null
3)JDK API中Set接口的实现类有:
package com.dxl.staticpar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetMethod {
public static void main(String[] args) {
//2. set接口的实现类的对象(Set接口对象),不能存放重复的元素,可以添加一个nul
//3. set接口对象存放数据是无序(即添加的顺序和取出的顺序不一致”)
//4.注意:取出的顺序的顺序虽然不是添加的顺序,但是他的固定.
Set set = new HashSet();
set.add("john");
set.add("yuyu");
set.add("john");
set.add("jack");
set.add(null);
set.add(null);
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("next = " + next);
}
for (Object o: set){
System.out.println("set = " + o);
}
}
}
Set接口的常用方法
和List接口一样, Set接口也是Collection的子接口,因此,常用方法和Collection接口一样.
Set接口的遍历方式
同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。
1.可以使用迭代器
2增强for
3.不能使用索引的方式来获取.
Set接口实现类-HashSet
HashSet的全面说明
- HashSet实现了Set接口
- HashSet实际上是HashMap。
3)可以存放null值,但是只能有一个null - HashSet不保证元素是有序的,取决于hash后,再确定索引的结果.
5)不能有重复元素/对象.在前面Set 接口使用已经讲过
package com.dxl.staticpar;
import java.util.HashSet;
import java.util.Set;
public class SetMethod {
public static void main(String[] args) {
Set hashSet = new HashSet();
hashSet.add(null);
hashSet.add(null);
System.out.println("hashSet = " + hashSet);
}
}
Set接口实现类-HashSet
HashSet底层机制说明
分析HashSet底层是HashMap, HashMap底层是(数组+链表+红黑树)
package com.dxl.staticpar;
import java.util.HashSet;
@SuppressWarnings({"all"})
public class SetMethod {
public static void main(String[] args) {
//1.在执行add方法后,会返回一个boolean值
// 2.如果添加成功,返回 true,否则返回false
// 3.可以通过remove指定删除哪个对象
HashSet set = new HashSet();
System.out.println(set.add("john"));
System.out.println(set.add("lucy"));
System.out.println(set.add("john"));
System.out.println(set.add("Rose"));
set.remove("john");
System.out.println("set = " + set);
set = new HashSet();
System.out.println("set = " + set);
set.add("lucy");
set.add("lucy");
set.add(new Dog("tom"));
set.add(new Dog("tom"));
System.out.println("set = " + set);
}
}
class Dog{
private String name;
public Dog(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
package com.dxl.staticpar;
public class HashSet_ {
public static void main(String[] args) {
Node[] table = new Node[16];
System.out.println("table = " + table);
Node john = new Node("John", null);
table[2] = john;
Node jack = new Node("jack", null);
john.next = jack;
System.out.println("table = " + table);
}
}
class Node{
Object item;
Node next;
public Node(Object item, Node next) {
this.item = item;
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"item=" + item +
", next=" + next +
'}';
}
}
package com.dxl.staticpar;
import java.util.HashSet;
import java.util.Objects;
public class HashSet_ {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
hashSet.add(new Employee("milan", 45));
hashSet.add(new Employee("smith",56));
hashSet.add(new Employee("milan",45));
System.out.println("hashSet = " + hashSet);
}
}
class Employee{
private String name;
private int age;
public Employee(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;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee employee = (Employee) o;
return getAge() == employee.getAge() && Objects.equals(getName(), employee.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
}
Set接口实现类-LinkedHashSet
LinkedHashSet的全面说明
1)LinkedHashSet是HashSet的子类
2) LinkedHashSet底层是一个 LinkedHashMap,底层维护了一个数组+双
向链表
3)LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使
用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的.
4)LinkedHashSet不允许添重复元素
package com.dxl.staticpar;
import java.util.LinkedHashSet;
import java.util.Set;
public class HashSet_ {
public static void main(String[] args) {
Set set = new LinkedHashSet();
set.add(new String("AA"));
set.add(423);
set.add(423);
set.add(new Custom("刘",45678));
set.add(489);
set.add("shh");
System.out.println("set = " + set);
//1.LinkedHashSet 加入顺序和取出元素/数据的顺序一致
//2. LinkedHashSet底层维护的是一个LinkedHashMap(是HashMap的子类)
// 3. LinkedHashSet底层结构〔数组table+双向链表)
//4.添加第一次时,直接将数组table扩容到16,存放的结点类型是 LinkedHashMapSEntry
//5.数组是 HashMap$Node[]存放的元素/数据是 LinkedHashMap$Entry类型
/*
继承关系是静态内部类
static class EntryK,v> extends HashMap.Node<K, V> {
Entry<K,V> before,after;
Entry(int hash,K key, V value,Node<K, V> next) {
super(hash,key, value,next);
}
}
*/
}
}
class Custom{
private String name;
private int no;
public Custom(String name, int no) {
this.name = name;
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNo() {
return no;
}
@Override
public String toString() {
return "Custom{" +
"name='" + name + '\'' +
", no=" + no +
'}';
}
public void setNo(int no) {
this.no = no;
}
}
Map接口和常用方法
Map接口实现类的特点
注意:这里讲的是JDK8的Map接口特点
1)Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
2) Map 中的key和 value可以是任何引用类型的数据,会封装到HashMap$Node对象中
3) Map中的key 不允许重复,原因和HashSet一样,前面分析过源码.
4) Map中的value可以重复
5) Map 的key可以为null, value也可以为null,注意key为null, 只能有一个,
value为null ,可以多个.
6)常用String类作为Map的key
7) key 和 value之间存在单向一对一关系,即通过指定的key 总能找到对应的value
package com.dxl.staticpar;
import java.util.HashMap;
import java.util.Map;
public class Map_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("12","哈加");
map.put("13","sh");
map.put("12","eh");
map.put(null,null);
map.put(null,"adb");
map.put("jfke",null);
map.put("hye",null);
map.put(1,"zhaj");
map.put(new Object(),"jfke");
System.out.println(map.get("12"));
System.out.println("map = " + map);
}
}
- Map存放数据的key-value示意图,一对k-v是放在一个Node中的,有因为Node实现了Entry 接口,有些书上也说一对k-v就是一个Entry
package com.dxl.staticpar;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Map_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("12","哈加");
map.put("13","sh");
//1.k-v最后是 HashMap$Node node = newNode(hash, key,value,null)
// 2.k-v为了方便程序员的遍历,还会创建 EntrySet集合,该集合存放的元素的类型 Entry,而一个Entry
// 对象就有k,v EntrySet<Entry<K,V>>即: transient Set<Hap. Entry<K,V>> entrySet;
//3. entrySet 中,定义的类型是Map.Entry ,但是实际上存放的还是 HashMap$Node
// 这时因为static class Node<K,V> implements Map.Entry<K, V>
//4.当把 HashMap$Node 对象存放到 entrySet 就方便我们的遍历,因为 Map.Entry 提供了重要方法
// K getKey(); v getValue();
Set set = map.entrySet();
System.out.println(set.getClass());
for (Object obj : set){
// System.out.println(obj.getClass();
// HashMap$Node
// 为了从 HashMap$Node 取出k-v
//1.先做一个向下转型
Map. Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() +"-" + entry.getValue() );
}
}
}
'Map接口常用方法
- put:添加
- remove:根据键删除映射关系
- get:根据键获取值
- size:获取元素个数
- isEmpty:判断个数是否为0
- clear:清除
- containsKey:查找键是否存在
package com.dxl.staticpar;
import java.util.HashMap;
import java.util.Map;
public class Map_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("大亨", new Book("", 100));
map.put("jd","hfej");
map.put("ejf",null);
map.put(null,"feef");
map.put("fe","fe");
System.out.println("map = " + map);
map.remove(null);
System.out.println("map = " + map);
}
}
class Book{
private String name;
private int money;
public Book(String name, int money) {
this.name = name;
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
}
Map接口和常用方法
Map接口遍历方法> Map遍历方式
1)containsKey:查找键是否存在
2) keySet:获取所有的键
3) entrySet:获取所有关系k-v
4) values:获取所有的值
package com.dxl.staticpar;
import java.util.*;
public class Map_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("邓超","孙俪");
map.put("王宝强","马蓉");
map.put("宋喆","马蓉");
map.put("刘令博", null);
map.put(null,"刘亦菲");
map.put("鹿晗","关晓彤");
Set keys = map.keySet();
for (Object obj : keys){
System.out.println(obj + "_" + map.get(obj));
}
Iterator iterator = keys.iterator();
while (iterator.hasNext()){
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
// 把所有的values取出来
Collection values = map.values();
// 可以使用所有collections使用的遍历方法
for (Object value:values){
System.out.println(value);
}
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()) {
Object next = iterator1.next();
System.out.println(next);
}
// EnterySet来获取k-v
Set entrySet = map.entrySet();
for (Object o : entrySet){
// 将o转成Map.Entry
Map.Entry m = (Map.Entry) o;
System.out.println(m.getKey() + "-" + m.getValue());
}
Iterator iterator2 = entrySet.iterator();
while (iterator2.hasNext()) {
Object next = iterator2.next();
System.out.println(next.getClass());
// 向下转型 Map.Entry
Map.Entry M = (Map.Entry) next;
System.out.println(M.getKey() + "-" + M.getValue());
}
}
}
Map接口实现类-HashMap
HashMap小结
- Map接口的常用实现类:HashMap、Hashtable和Properties.
- HashMap是 Map接口使用频率最高的实现类。
- HashMap是以key-val对的方式来存储数据[HashMap$Node]Entry
- key不能重复,但是是值可以重复,允许使用null键和null值。
5)如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)
6)与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的. - HashMap没有实现同步,因此是线程不安全的
package com.dxl.staticpar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapExercise {
public static void main(String[] args) {
Map hashMap = new HashMap();
hashMap.put(1,new Emp("jack",5000,1));
hashMap.put(2,new Emp("lili",5800,2));
hashMap.put(3,new Emp("yue",5500,3));
// 两种遍历方式
Set keySet = hashMap.keySet();
for (Object key: keySet){
Emp emp =(Emp) hashMap.get(key);
if (emp.getSal() > 5500){
System.out.println(emp);
}
}
Set entrySet = hashMap.entrySet();
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry) iterator.next();
Emp emp = (Emp) entry.getValue();
if (emp.getSal() > 5500){
System.out.println(emp);
}
}
}
}
class Emp{
private String name;
private double sal;
private int id;
public Emp(String name, double sal, int id) {
this.name = name;
this.sal = sal;
this.id = id;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", sal=" + sal +
", id=" + id +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
扩容机制[和HashSet相同]
- HashMap底层维护了Node类型的数组table,默认为null
2)当创建对象时,将加载因子(loadfactor)初始化为0.75.
3)当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素。
如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
4)第1次添加,则需要扩容table容量为16,临界值(threshold)为12.
5)以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推.
6)在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),
table的大小 >= MIN_TREEIFY_ CAPACITY(默认64),就会进行树化(红黑树)
package com.dxl.staticpar;
import java.util.HashMap;
public class MapExercise {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
for (int i = 1; i < 12; i++) {
hashMap.put(new A(i),"heu");
}
System.out.println("hashMap = " + hashMap );
}
}
class A{
private int num;
public A(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
// @Override
// public boolean equals(Object o) {
// if (this == o) return true;
// if (!(o instanceof A)) return false;
// A a = (A) o;
// return num == a.num;
// }
@Override
public int hashCode() {
return 100;
}
@Override
public String toString() {
return "\nA{" +
"num=" + num +
'}';
}
}
Map接口实现类-Hashtable
HashTable的基本介绍
1)存放的元素是键值对:即K-V
2) hashtable的键和值都不能为null,否则会抛出空指针异常
'3) hashTable使用方法基本上和HashMap一样
4) hashTable是线程安全的,hashMap是线程不安全的
//1。底层有数组 Hashtable$Entry[]初始化大小为11
//2.临界值threshold 8 = 11 * 0.75
//3.扩容:按照自己的扩容机制来进行即可.
Map接口实现类-Properties
●基本介绍
1.Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。
2.他的使用特点和Hashtable类似
3.Properties还可以用于从 xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
4.说明:工作后xxx.properties文件通常作为配置文件。
package com.dxl.staticpar;
import java.util.Properties;
public class Properties_ {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put( "john",100);
// properties.put(null,100);不能放空键和空值
// properties.put("john", null);
properties.put("lucy",100);
properties.put("lic",100);
properties.put("lic", 88);//相同的key,value被替换
System.out.println("Properties = " + properties);
System.out.println(properties.get("lic"));
properties.remove("lic");
System.out.println("per = " + properties);
properties.put("john","雨夜");
System.out.println(properties);
}
}
package com.dxl.staticpar;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSet_ {
public static void main(String[] args) {
//1.当我们使用无参构造器,创建TreeSet时,仍然是无序的
//2.老师希望添加的元素,按照字符串大小来排序
//3.使用TreeSet提供的一个构造器,可以传入一个比较器
// TreeSet treeSet = new TreeSet();
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o2) .compareTo((String) o1);
}
});
treeSet.add("jack");
treeSet.add("tom");
treeSet.add("sh");
treeSet.add("a");
System.out.println("treeSet = " + treeSet);
// 底层构造器把传入的对象赋给了TreeMap
}
}
package com.dxl.staticpar;
import java.util.Comparator;
import java.util.TreeMap;
public class TreeSet_ {
public static void main(String[] args) {
//使用默认的构造器,创建TreeMap,是无序的(也没有排序)
// TreeMap treeMap = new TreeMap();
TreeMap treeMap = new TreeMap(new Comparator()
{
@Override
public int compare(Object o1, Object o2) {
// 按字符K的大小排序
// return ((String) o1).compareTo((String) o2);
// 按照K的长度大小排序
return ((String) o1).length() - ((String) o2).length();
}
});
treeMap.put("jax","fe");
treeMap.put("tom","汤姆");//按长度加入不了,不是替换
treeMap.put( "kristina","克瑞斯提诺");
treeMap.put( "smith","斯密斯");
System.out.println("treeMap = " + treeMap);
}
}
Collections工具类
Collections工具类介绍
- Collections是一个操作Set、List和 Map等集合的工具类
- Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作排序操作:(均为static方法)
- reverse(List):反转List 中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List集合元素按升序排序
- sort(List,Comparator):根据指定的Comparator产生的顺序对 List集合元素进行排序
- swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Collections_ {
public static void main(String[] args) {
List list = new ArrayList();
list.add("tom");
list.add("smoith");
list.add("kogn");
list.add("milan");
// 翻转
Collections.reverse(list);
System.out.println("list = " + list);
//shuffle(List):对List集合元素进行随机排序
// Collections.shuffle(list);
// System.out.println(list);
// sort(List):根据元素的自然顺序对指定 List集合元素按升序排序
Collections.sort(list);
System.out.println("自然排序:" + list);
// sort(List,Comparator):根据指定的Comparator产生的顺序对List 集合元素
// 我们希望按照字符串的长度大小排序
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1,Object o2){
return ((String)o1).length() - ((String)o2).length();
}
});
System.out.println(list);
// swap(List,int, int):将指定 list 集合中的i处元素和j处元素进行交换
Collections.swap(list,0,1);
System.out.println("list = " + list);
}
}
Collections工具类
●查找、替换
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection, Comparator):根据Comparator 指定的顺序,返回给定集合中的最大元素
- Object min(Collection)
4)Object min(Collection,Comparator) - int frequency(Collection,object):返回指定集合中指定元素的出现次数
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal, Object newVal):使用新值替换List对象的所有旧值
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Collections_ {
public static void main(String[] args) {
List list = new ArrayList();
list.add("tom");
list.add("smoith");
list.add("kogn");
list.add("milan");
// 翻转
Collections.reverse(list);
System.out.println("list = " + list);
//shuffle(List):对List集合元素进行随机排序
// Collections.shuffle(list);
// System.out.println(list);
// sort(List):根据元素的自然顺序对指定 List集合元素按升序排序
Collections.sort(list);
System.out.println("自然排序:" + list);
// sort(List,Comparator):根据指定的Comparator产生的顺序对List 集合元素
// 我们希望按照字符串的长度大小排序
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1,Object o2){
return ((String)o1).length() - ((String)o2).length();
}
});
System.out.println(list);
// swap(List,int, int):将指定 list 集合中的i处元素和j处元素进行交换
Collections.swap(list,0,1);
System.out.println("list = " + list);
//object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素System.out.println("自然顺序最大元素=" +Collections.max(list));
//Object max(Collection,Comparator):根据Comparator 指定的顺序,返回给定集合中的最大元素
// 比如,我们要返回长度最大的元素
Object maxObject = Collections.max(list,new Comparator() {
@Override
public int compare(Object o1,Object o2) {
return ((String)o1).length() - ((String)o2).length();
}
});
System.out.println("长度最大的元素:" + maxObject);
//object min(collection)
//object min(Collection,Comparator)
//int frequency(Collection,Object):返回指定集合中指定元素的出现次数
System.out.println("tom出现的次数=" + Collections.frequency(list,"tom"));
//void copylList dest,List src):将src中的内容复制到dest中
ArrayList dest = new ArrayList();
//为了完成一个完整拷贝,我们需要先给dest赋值,大小和list.size()一样
for(int i = 0; i< list.size(); i++) {
dest.add("");
}
//拷贝
Collections.copy(dest,list);
System.out.println("dest=" +dest);
//boolean replaceAli(List list,Object oldVal,Object newVal):使用新值替换 List对象的所有旧值
Collections.replaceAll(list,"tom","汤姆");
System.out.println(list);
}
}
package com.dxl.staticpar;
import java.util.ArrayList;
public class HomeWork {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new News("新冠确诊病例超千万,数百万印度教信徒赴恒河\"圣浴\"引民众担忧\n"));
arrayList.add(new News("男子突然想起2个月前钓的鱼还在网兜里,捞起一看赶紧放生\n"));
int size = arrayList.size();
for (int i = size - 1; i >= 0 ; i--) {
News news = (News)arrayList.get(i);
System.out.println(News.processTitle(news.getTitle()));
}
}
}
class News{
private String title;
private String content;
public News(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "News{" +
"title='" + title + '\'' +
'}';
}
public static String processTitle(String title){
if (title == null){
return "";
}
if (title.length() > 15){
return title.substring(0,15) + "...";
}else{
return title;
}
}
}
package com.dxl.staticpar;
import java.util.*;
public class HomeWork {
public static void main(String[] args) {
Map map = new HashMap();
map.put("jack",650);
map.put("tom",1200);
map.put("simth",2900);
System.out.println("map = " + map);
map.put("jack",2600);
System.out.println("map = " + map);
Set keySet = map.keySet();
for (Object o : keySet){
map.put(o, (Integer)map.get(o) + 100);
}
System.out.println(map);
Set entrySet = map.entrySet();
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry next = (Map.Entry)iterator.next();
System.out.println(next.getKey() + "-" +next.getValue());
}
Collection values = map.values();
for (Object value : values){
System.out.println(value);
}
}
}
泛型的理解和好处
使用传统方法的问题分析
1)不能对加入到集合ArrayList中的数据类型进行约束(不安全)
2)遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响
泛型快速体验-用泛型来解决前面的问题
ArrayList arrayList = new ArrayList{};
泛型的理解和好处
●泛型的好处
1)编译时,检查添加元素的类型,提高了安全性
2)减少了类型转换的次数,提高效率
√不使用泛型
Dog -加入->Object -取出-> Dog //放入到ArrayList 会先转成Object,在取出时,还需要转换成Dog
√使用泛型
Dog -> Dog -> Dog!/放入时,和取出时,不需要类型转换,提高效率
3)不再提示编译警告
package com.dxl.staticpar;
import java.util.ArrayList;
//@SuppressWarnings({"all"})
public class generic_ {
public static void main(String[] args) {
ArrayList<Dog> arrayList = new ArrayList<Dog>();//表示存放在ArrayList集合中的元素只能是Dog类型
arrayList.add(new Dog("旺财",56));
arrayList.add(new Dog("发财",12));
arrayList.add(new Dog("小黄",4));
// arrayList.add(new Cat("招财猫",12));
// 遍历可以直接取出Dog类型,而不是Object类型
for (Dog dog:arrayList){
// Dog dog = (Dog)o;
System.out.println(dog.getName() + "_" + dog.getAge());
}
}
}
class Dog{
private String name;
private int age;
public Dog(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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Cat{
private String name;
private int age;
public Cat(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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
泛型介绍
int a = 10;
泛(广泛)型(类型)=> Integer,String,Dog
1)泛型又称参数化类型,是Jdk5.0出现的新特性,解决数据类型的安全性问题2)在类声明或实例化时只要指定好需要的具体的类型即可。
3) Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生
ClassCastException异常。同时,代码更加简洁、健壮。
4)泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方
法的返回值的类型,或者是参数类型.
public class ArrayList{} E称为泛型,那么Dog->E
package com.dxl.staticpar;
public class Generic_ {
public static void main(String[] args) {
//E 的具体数据类型,在定义时确定,即编译时
Person<String> stringPerson = new Person<String>("哈哈哈哈");
/*
Person中的E 全部用String表示
*/
Person<Integer> integerPerson = new Person<Integer>(100);
/*
Person中的E 全部用Integer表示
*/
integerPerson.show();
}
}
//泛型的作用是;可以在类声明时通过一个标识表示类中某个属性的类型,
// 或者是某个方法的返回值的类型,或者是参数类型
class Person<E>{
E s;//E 表示 s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间就确定E是什么类型
public Person(E s) {//E也可以是参数类型
this.s = s;
}
public E f(){//返回类型使用E
return s;
}
public void show(){
System.out.println(s.getClass());
}
}
泛型的语法
●泛型的声明
interface接口0和class类<K.V>{}
//比如: List , ArrayList
说明:
1)其中,T,K,V不代表值,而是表示类型。
.2)任意字母都可以。常用T表示,是Type的缩写泛型的实例化:
要在类名后面指定类型参数的值(类型)。如:
- List strList = new ArrayList();
- Iterator iterator = customers.iterator();
package com.dxl.staticpar;
import java.util.*;
public class Generic_ {
public static void main(String[] args) {
// 使用泛型给hashSet创建对象
HashSet<Student> students = new HashSet<>();
students.add(new Student("jack",12));
students.add(new Student("tom",23));
students.add(new Student("mary",22));
for (Student s : students){
System.out.println(s);
}
// 使用泛型给HashMap创建对象
HashMap<String, Student> stringStudentHashMap = new HashMap<>();
stringStudentHashMap.put("jack",new Student("jack",12));
stringStudentHashMap.put("tom",new Student("tom",23));
stringStudentHashMap.put("mary",new Student("mary",22));
// 迭代器,EntrySet
/*
public Set<Nap .Entry<K, V>> entrySet() {
Set<Map.Entry<K, V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
*/
Set<Map.Entry<String, Student>> entries = stringStudentHashMap.entrySet();
/*
public final Iterator<Map. Entry<K, V>> iterator() {
return new EntryIterator();
}
*/
Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Student> next = iterator.next();
System.out.println(next.getKey() + " " + next.getValue());
}
}
}
class Student{
private String name;
private int age;
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
泛型使用的注意事项和细节
1.interface List{} , public class HashSet{}等等
说明:T,E正只能是引用类型
看看下面语句是否正确?:
List list = new ArrayList();//正确
List list2 = new ArrayList();//错误
2.在指定泛型具体类型后,可以传入该类型或者其子类类型
3.泛型使用形式
List list1 =new ArrayList();
List list2 = new ArrayList<>();
package com.dxl.staticpar;
public class Generic_ {
public static void main(String[] args) {
Pig<A> aPig = new Pig<A>(new A());
Pig<A> aPig1 = new Pig<>(new B());
aPig.show();
aPig1.show();
}
}
class A{}
class B extends A{}
class Pig<E>{
E e;
public Pig(E e) {
this.e = e;
}
public void show(){
System.out.println(e.getClass());
}
}
4.如果我们这样写 List list3 = new ArrayList();默认给它的泛型是就是Object ]即:
package com.dxl.staticpar;
public class MyDate implements Comparable<MyDate> {
private int year;
private int month;
private int dar;
public MyDate(int year, int month, int dar) {
this.year = year;
this.month = month;
this.dar = dar;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDar() {
return dar;
}
public void setDar(int dar) {
this.dar = dar;
}
@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", dar=" + dar +
'}';
}
@Override
public int compareTo(MyDate o) {//把对年月日的比较
// name相同,比较birthday
int yearMinus = year - o.getYear();
if (yearMinus != 0){
return yearMinus;
}
// 如果年相同,比较months
int monthMinus = month - o.getMonth();
if (monthMinus != 0){
return monthMinus;
}
return dar- o.getDar();
}
}
package com.dxl.staticpar;
public class Employee {
private String name;
private double sal;
private MyDate birthday;
public Employee(String name, double sal, MyDate birthday) {
this.name = name;
this.sal = sal;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "\nEmployee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}';
}
}
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.Comparator;
public class Generic_ {
public static void main(String[] args) {
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("tom",20000,new MyDate(2000,11,5)));
employees.add(new Employee("jack",12000,new MyDate(1980,12,12)));
employees.add(new Employee("tom",50000,new MyDate(1980,10,10)));
System.out.println("employees = " + employees);
System.out.println("========对雇员进行排序===========");
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
if (!(o1 instanceof Employee && o2 instanceof Employee)) {
System.out.println("类型不正确!");
return 0;
}
else {
int i = o1.getName().compareTo(o2.getName());
if (i != 0) {
return i;
}
return o1.getBirthday().compareTo(o2.getBirthday());
}
}
});
System.out.println("=====排序后的结果======");
System.out.println("employees = " + employees);
}
}
自定义泛型
自定义泛型类(难度)
基本语法
class类名<T,R…>{成员
}
注意细节
1)普通成员可以使用泛型(属性、方法)
2)使用泛型的数组,不能初始化
3)静态方法中不能使用类的泛型
4)泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)5)如果在创建对象时,没有指定类型,默认为Object
package com.dxl.staticpar;
import java.util.Arrays;
public class Generic_ {
public static void main(String[] args){
Tiger<Double, String, Integer> g = new Tiger<>("john");
g.setT(10.9);
System.out.println(g);
Tiger g2 = new Tiger("john~~~");
g2.setT("yy");
System.out.println("g2 = " + g2);
}
}
//1.Tiger后面泛型,所以我们把 Tiger 就称为自定义泛型类
//2.T,R,H泛型的标识符,一般是单个大写字母
//3.泛型标识符可以有多个。
//4.普通成员可以使用泛型〔属性、团法)
//5.使用泛型的数组不能初始化
//6.静态方法不能使用泛型,
//因为静态是和类相关的,在类加载时,对象还没有创建
//所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
class Tiger<T,R,M>{
String name;
R r;
M m;
T t;
T[] ts;//无法确定T的类型,无法在内存开空间,不能初始化
// static R r1;
public Tiger(String name) {
this.name = name;
}
public Tiger(String name, R r, M m, T t) {
this.name = name;
this.r = r;
this.m = m;
this.t = t;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public R getR() {
return r;
}
public void setR(R r) {
this.r = r;
}
public M getM() {
return m;
}
public void setM(M m) {
this.m = m;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
@Override
public String toString() {
return "Tiger{" +
"name='" + name + '\'' +
", r=" + r +
", m=" + m +
", t=" + t +
", ts=" + Arrays.toString(ts) +
'}';
}
}
自定义泛型接口>基本语法
interface接口名<T,R…>{}
注意细节
1)接口中,静态成员也不能使用泛型(这个和泛型类规定一样)
2)泛型接口的类型,在继承接口或者实现接口时确定
3)没有指定类型,默认为Object
package com.dxl.staticpar;
public class GenericInterface {
public static void main(String[] args) {
}
}
interface IUsb<U, R>{
int n = 10;
R get(U u);//普通方法可以使用方法
void hi(R r);
void run(R r1,R r2,U u1, U u2);
//在jdk8 中,可以在接口中,使用默认方法
default R method(U u){
return null;
}
}
//继承接口时需要指定类型
interface IA extends IUsb<String ,Double>{
}
//当我们去实现IA接口时,因为IA在继承IUsU 接口时,指定了U为String R为Double
// ,在实现IUsu接口的方法时,使用String替换,是Double替换R
class AA implements IA{
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double aDouble) {
}
@Override
public void run(Double r1, Double r2, String u1, String u2) {
}
@Override
public Double method(String s) {
return IA.super.method(s);
}
}
//实现接口时,直接指定泛型接口类型
//实现接口时,直接指定泛型接口的类型
// 给U指定Integer给R指定了 Float
//所以,当我们实现IUsb方法时,会使用Integer替换U,使用Float替换R
class BB implements IUsb<Integer, Float>{
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float aFloat) {
}
@Override
public void run(Float r1, Float r2, Integer u1, Integer u2) {
}
@Override
public Float method(Integer integer) {
return IUsb.super.method(integer);
}
}
//等价与类型为Object
class CC implements IUsb{
@Override
public Object get(Object o) {
return null;
}
@Override
public void hi(Object o) {
}
@Override
public void run(Object r1, Object r2, Object u1, Object u2) {
}
@Override
public Object method(Object o) {
return IUsb.super.method(o);
}
}
自定义泛型方法
基本语法
修饰符<T,R…>返回类型方法名(参数列表){}
注意细节
1.泛型方法,可以定义在普通类中,也可以定义在泛型类中
2.当泛型方法被调用时,类型会确定
3. public void eat(E e) (),修饰符后没有<T,R…> eat方法不是泛型方法,而是使用了泛型
package com.dxl.staticpar;
import java.util.ArrayList;
@SuppressWarnings({"all "})
public class GenericInterface {
public static void main(String[] args) {
Car car = new Car();
car.fly("玉玉", 100);//当调用方法使,传入参数,编译器会确定类型
car.fly(100,5.69);//包含了自动装箱
// T ---> String, R ---> ArrayList
Fish<String , ArrayList> fish = new Fish<>();
fish.hello(new ArrayList(),11.3f);
}
}
class Car{
public void run(){
}
public <T, R> void fly(T t, R r){
System.out.println(t.getClass());
System.out.println(r.getClass());
}
public void show(){
}
}
class Fish<T, R> {
public void run(){
}
public <U,M> void eat(U u,M m){
}
public void hi(T t){
//不是泛型方法,是hi方法使用了类型声明的泛型
}
public <K> void hello(R r,K k){
//泛型方法,可以使用类声明的泛型,也可以使用自己声明的泛型
System.out.println(r.getClass());
System.out.println(k.getClass());
}
}
泛型的继承和通配符
1)泛型不具备继承性
List list = new ArrayList0);//对吗? 不对
2)<?>︰支持任意泛型类型
3)<? extends A>:支持A类以及A类的子类,规定了泛型的上限
4)<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
package com.dxl.staticpar;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings({"all "})
public class GenericInterface {
public static void main(String[] args) {
Object o = new String("xx");
//举例说明下面三个方法的使用
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
printCollection(list5);
printCollection(list1);
printCollection(list2);
printCollection(list3);
printCollection(list4);
printCollection2(list3);
printCollection2(list4);
printCollection2(list5);
printCollection3(list1);
printCollection3(list3);
}
//List<?>表示 任意的泛型类型都可以接受
public static void printCollection(List<?> c){
for (Object object : c){//通配符,取出时,就是Object
System.out.println(object);
}
}
// 规定泛型的上限
public static void printCollection2(List<? extends AA> c){
for (Object object : c){//通配符,取出时,就是Object
System.out.println(object);
}
}
// 规定泛型的下限
public static void printCollection3(List<? super AA> c){
for (Object object : c){//通配符,取出时,就是Object
System.out.println(object);
}
}
}
class AA{
}
class BB extends AA{
}
class CC extends BB{
}
JUnit
为什么需要JUnit
1.一个类有很多功能代码需要测试,为了测试,就需要写入到main方法中。
2.如果有多个功能代码测试,就需要来回注销,切换很麻烦
3.如果可以直接运行一个方法,就方便很多,并且可以给出相关信息,就好了-> JUnit
●基本介绍
1.JUnit是一个Java语言的单元测试框架
2.多数Java的开发环境都已经集成了JUnit作为单元测试的工具
package com.dxl.staticpar;
import org.junit.jupiter.api.Test;
public class JUnit_ {
public static void main(String[] args) {
}
@Test
public void m1(){
System.out.println("m1()方法被调用!");
}
@Test
public void m2(){
System.out.println("m2()方法被调用!");
}
}
package com.dxl.staticpar;
public class User {
private int id;
private int age;
private String name;
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
package com.dxl.staticpar;
import java.util.*;
public class DAO<T> {
private Map<String , T> map = new HashMap<>();
public T get(String id){
return map.get(id);
}
public void update(String id, T entity){
map.put(id,entity);
}
//遍历map [k-v],将map的所有value(entity),封装到ArrayList返回即可
public List<T> list(){
List<T> list = new ArrayList<>();
//遍历map
Set<String> keySet = map.keySet();
for (String key:keySet){
list.add(map.get(key));
}
return list;
}
public void delete(String id){
map.remove(id);
}
public void save(String id, T entity){
map.put(id,entity);
}
}
package com.dxl.staticpar;
import org.junit.jupiter.api.Test;
import java.util.List;
public class HomeWork {
public static void main(String[] args) {
}
@Test
public void testList(){
DAO<User> dao = new DAO<>();
dao.save("001",new User(1,10,"jacl"));
dao.save("002",new User(2,20,"fefe"));
dao.save("003",new User(3,30,"ege"));
List<User> list = dao.list();
System.out.println("list = " + list);
dao.update("003",new User(3,56,"j8"));
list = dao.list();
System.out.println("list = " + list);
dao.delete("001");
list = dao.list();
System.out.println("list = " + list);
System.out.println("id = 0003" + dao.get("003"));
}
}