Java基础 - 7 - 常用API(三)

API(全称 Application Programming Interface:应用程序编程接口)

API就是Java帮我们已经写好的一些程序,如类、方法等,可以直接拿过来用

JDK8 API文档Java Platform SE 8


一. JDK8之前传统的日期、时间

1.1 Date

        代表的是日期和时间

构造器说明
public Date()创建一个Date对象,代表的是系统当前此刻日期时间
public Date(long time)把时间毫秒值转换成Date日期对象
常见方法说明
public long getTime()返回从1970年1月1日 00:00:00走到此刻的总的毫秒数
public void setTime(long time)设置日期对象的时间为当前时间毫秒值对应的时间
//demo
public class demo {
    public static void main(String[] args) {
        //创建一个Date对象,代表的是系统当前此刻日期时间
        Date d = new Date();
        System.out.println(d);

        //返回从1970年1月1日 00:00:00走到此刻的总的毫秒数
        long time = d.getTime();
        System.out.println(time);

        //把时间毫秒值转换成Date日期对象
        System.out.println(new Date(1473913749209L));

        //直接把日期对象的时间通过setTime()方法进行修改
        Date d3 = new Date();
        d3.setTime(1473913749209L);
        System.out.println(d3);
    }
}

1.2 SimpleDateFormat

        SimpleDateFormat代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式(格式化和解析日期)

常见构造器说明
public SimpleDateFormat(String pattern)创建简单日期格式化对象,并封装时间的格式
格式化时间的方法说明
public final String format(Date date)将日期格式化成日期/时间字符串
public final String format(Object time)将时间毫秒值式化成日期/时间字符串
public Date parse(String source)把字符串时间解析成日期对象

//demo
public class demo {
    public static void main(String[] args) throws ParseException {
        Date d = new Date();
        System.out.println(d);

        long time = d.getTime();
        System.out.println(time);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
        String s1 = sdf.format(d);
        System.out.println(s1);
        String s2 = sdf.format(time);
        System.out.println(s2);

        System.out.println("======================");

        //SimpleDateFormat解析字符串时间称为日期对象
        String dateStr = "2024-05-20 13:14:15";
        //创建SimpleDateFormat对象,指定的时间格式必须与被解析的时间格式一致,否则会出问题
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date a = sdf1.parse(dateStr);
        System.out.println(a);
    }
}

练习:秒杀活动

//demo
public class demo {
    public static void main(String[] args) throws ParseException {
        //活动开始和结束的时间用String保存
        String start = "2023年11月11日 0:0:0";
        String end = "2023年11月11日 0:10:0";
        //用户的下单时间用String保存
        String datestr1 = "2023年11月11日 0:01:18";
        String datestr2 = "2023年11月11日 0:10:51";

        //将用户下单时间从String类型转换成Date类型再到long型(时间毫秒值)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date start_date = sdf.parse(start);
        Date end_date = sdf.parse(end);
        Date d1 = sdf.parse(datestr1);
        Date d2 = sdf.parse(datestr2);

        long start_time = start_date.getTime();
        long end_time = end_date.getTime();
        long d1_time = d1.getTime();
        long d2_time = d2.getTime();

        System.out.println(isOK(d1_time,start_time,end_time));
        System.out.println(isOK(d2_time,start_time,end_time));
    }

    public static String isOK(long d,long start,long end) {
        if(d >= start && d <= end){
            return "成功参与该活动";
        }else{
            return "未能成功参与该活动";
        }
    }
}

1.3 Calendar

        代表的是系统此刻时间对应的日历,通过它可以单独获取、修改时间中的年、月、日、时、分、秒等

方法名说明
public static Calendar getInstance()获取当前日历对象
public int get(int field)获取日历中的某个信息
public final Date getTime()获取日期对象
public long getTimeInMillis()获取时间毫秒值
public void set(int field,int value)修改日历的某个信息
public void add(int field,int amount)为某个信息增加/减少指定的值

注意:calendar是可变对象,一旦修改后其对象本身表示的时间将产生变化

//demo
public class demo {
    public static void main(String[] args) {
        Calendar rightNow = Calendar.getInstance();
        System.out.println(rightNow); //month从0开始记录

        //获取日历中的某个信息
        int year = rightNow.get(Calendar.YEAR);
        System.out.println(year);

        int days = rightNow.get(Calendar.DAY_OF_YEAR);
        System.out.println(days);

        //拿到日历中记录的日期对象
        Date now = rightNow.getTime();
        System.out.println(now); //当前月份

        //拿到日历中记录的时间毫秒值
        long time = rightNow.getTimeInMillis();
        System.out.println(time);

        //修改日历中的某个信息
        rightNow.set(Calendar.MONTH,9);  //把现在日历中的月份值修改成10月份(month从0开始记录)
        System.out.println(rightNow);  //MONTH=9
        Date m_now = rightNow.getTime();
        System.out.println(m_now);   //Oct

        //为某个信息增加或者减少指定值
        rightNow.add(Calendar.DAY_OF_YEAR,100);
        rightNow.add(Calendar.DAY_OF_YEAR,-10);
        System.out.println(rightNow);
        System.out.println(rightNow.getTime());
    }
}

二. JDK8开始新增的日期、时间

//demo
public class demo {
    //JDK8之前传统的时间API 不推荐使用
    //JDK8开始之后新增的时间API 推荐使用
    public static void main(String[] args) {
        Date d = new Date();
        //1.设计不合理,使用不方便,很多都被淘汰了
        System.out.println(d.getYear());

        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);   //要用Calendar.YEAR,使用不方便
        System.out.println(year);

        //2.传统的时间API都是可变对象,修改后会丢失最开始的时间信息

        //3.线程不安全
        //多用户同时使用同一个对象,会出现问题

        //4.不能精确到纳秒,只能精确到毫秒
        //1s(秒)=1000ms(毫秒)
        //1毫秒 = 1000微秒
        //1微秒 = 1000纳秒
        System.out.println(c.getTimeInMillis()); //毫秒级
    }

}

 JDK8开始新增的日期、时间

2.1 LocalDate、LocalTime、LocalDateTime

LocalDate:代表本地日期(年、月、日、星期)

LocalTime:代表本地时间(时、分、秒、纳秒)

LocalDateTime:代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)

它们获取对象的方案

方法名实例
public static Xxxx now()  获取系统当前时间对应的该对象

LocalDate ld = LocalDate.now();

LocalTime lt = LocalTime.now();

LocalDateTime ldt = LocalDateTime.now();

public static Xxxx of(…) 获取指定时间对象

LocalDate ld = LocalDate.of(9999,12,31);

LocalTime lt = LocalTime.now();

LocalDateTime ldt = LocalDateTime.now();

LocalDate的常用API(都是处理年、月、日、星期相关的)

LocalTime的常用API(都是处理时、分、秒、纳秒相关的) 

LocalDateTime的常用API(可以处理年、月、日、星期、时、分、秒、纳秒相关的) 

2.2 ZoneId(时区)、ZonedDateTime(带时区的时间)

        世界标准时间(UTC)

        中国标准时间:世界标准时间(UTC)+8小时

ZoneId:代表时区Id(如Asia/Shanghai)

//demo
public class demo {
    public static void main(String[] args) {
        //ZoneId
        //public static ZoneId systemDefault():获取系统默认的时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId); //Asia/Shanghai  //因为直接zoneId时调用toString方法,toString返回的就是getId()
        System.out.println(zoneId.getId()); //Asia/Shanghai

        //public static Set<String> getAvailableZoneIds():获取Java支持的全部时区id
        System.out.println(ZoneId.getAvailableZoneIds());;

        //public static ZoneId of(String zoneId) :把某个时区id封装成ZoneId对象
        ZoneId zoneId1 = ZoneId.of("Asia/Aden");

        //ZonedDateTime:带时区的时间
        //public static ZonedDateTime now(ZoneId zone):获取某个时区的ZonedDateTime对象
        ZonedDateTime now = ZonedDateTime.now(zoneId1);
        System.out.println(now);
        //获取世界标准时间
        ZonedDateTime now_UTC = ZonedDateTime.now(Clock.systemUTC());
        System.out.println(now_UTC);
        //获得系统默认时间
        ZonedDateTime now2 = ZonedDateTime.now();
        System.out.println(now2);

        //Calendar c = Calendar.getInstance(TimeZone.getTimeZone(zoneId1));
    }
}

2.3 Instant

        Instant 时间线上得某个时刻/时间戳

        通过获取Instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00开始走到此刻的总秒数+不够1秒的纳秒数

Instant对象的作用:做代码的性能分析,或记录用户操作的某个时间点

        传统的Date类,只能精确到毫秒,并且是可变对象;新增的Instant类,可以精确到纳秒,并且是不可变对象,推荐用Instant代替Date

        Instant类相较于LocalDateTime类,可以直接获得从1970-01-01 00:00:00开始走到此刻的总秒数+不够1秒的纳秒数

2.4 DateTimeFormatter

        格式化器,用于时间的格式化、解析,线程安全

         SimpleDateFormat 线程不安全;DateTimeFormatter 线程安全

//demo
public class demo {
    public static void main(String[] args) {
        //创建一个日期时间格式化器对象出来
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //对时间进行格式化
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        String s = dtf.format(now);  //正向格式化
        System.out.println(s);

        //格式化时间,其实还有一种方法
        String s1 = now.format(dtf);  //反向格式化
        System.out.println(s1);

        //解析时间,一般使用LocalDateTime提供的解析方法来解析
        String dataStr = "1999-12-31 23:59:59";
        LocalDateTime ldt = LocalDateTime.parse(dataStr,dtf);
        System.out.println(ldt);
    }
}

2.5 Period(一段时期)

        可以用于计算两个LocalDate对象相差的年数、月数、天数

//demo
public class demo {
    public static void main(String[] args) {
        LocalDate ld1 = LocalDate.of(2000,1,1);
        LocalDate ld2 = LocalDate.of(2099,5,20);

        //创建Period对象,封装两个日期对象
        Period period = Period.between(ld1,ld2);

        //通过period对象获取两个日期对象相差的信息
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
    }
}

2.6 Duration(持续时间)

        可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等对象

//demo
public class demo {
    public static void main(String[] args) {
        LocalDateTime ldt1 = LocalDateTime.of(2000,1,1,0,0,0);
        LocalDateTime ldt2 = LocalDateTime.of(2099,5,20,13,14,15);

        //创建Duration对象,封装两个日期对象
        Duration duration = Duration.between(ldt1,ldt2);

        //通过period对象获取两个日期对象相差的信息
        System.out.println(duration.toDays());   //间隔多少天
        System.out.println(duration.toHours());   //间隔多少小时
        System.out.println(duration.toMinutes());   //间隔多少分钟
        System.out.println(duration.toMillis());   //间隔多少毫秒
        System.out.println(duration.toNanos());   //间隔多少纳秒
    }
}

三. Arrays

        Arrays用来操作数组的一个工具类

注意:如果数组中存储的是对象,不能直接用Arrays.sort()排序

//demo
public class demo {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};

        //public static String toString(int[] a) 返回数组的内容
        System.out.println(Arrays.toString(arr));  //[1, 2, 3, 4, 5, 6]

        //拷贝数组(指定范围  包前不包后)
        //public static 类型[] copyOfRange(类型[] arr, int 起始索引, int 结束索引)
        int[] arr1 = Arrays.copyOfRange(arr,0,5);  //[1, 2, 3, 4, 5]
        System.out.println(Arrays.toString(arr1));

        //拷贝数组(可以指定新数组的长度):可做数组扩容
        //public static 类型[] copyOf(类型[] arr, int newLength)
        int[] arr2 = Arrays.copyOf(arr,10);
        System.out.println(Arrays.toString(arr2));  //[1, 2, 3, 4, 5, 6, 0, 0, 0, 0]
        int[] arr3 = Arrays.copyOf(arr,3); //容量没有原数组大的话,就取原数组的前newLength个
        System.out.println(Arrays.toString(arr3));  //[1, 2, 3]

        double[] dArr = {13.14,16.8,99.9,20};
    //需求:把dArr中的数据打八折
        //把数组中的原数据改为新数据又存进去
        //public static void setAll(double[] array, IntToDoubleFunction generator)
        Arrays.setAll(dArr, new IntToDoubleFunction(){
            @Override
            public double applyAsDouble(int value) {
                //value : 数组索引值 取 0 1 2……
                //return dArr[value] * 0.8;  //直接进行浮点数的计算可能出现结果失真的问题
                //用BigDecimal解决浮点型数据运算失真问题
                BigDecimal bd1 = BigDecimal.valueOf(dArr[value]);  //把double型转换成BigDecimal型
                BigDecimal bd2 = BigDecimal.valueOf(0.8);
                BigDecimal rs = bd1.multiply(bd2);  //乘法结果
                return rs.doubleValue();
            }
        });
        System.out.println(Arrays.toString(dArr));  //[10.512, 13.44, 79.92, 16.0]


        //对数组进行排序(默认是升序排序)
        //public static void sort(类型[] arr)
        Arrays.sort(dArr);
        System.out.println(Arrays.toString(dArr));  //[10.512, 13.44, 16.0, 79.92]

        //如果数组中存储的是对象,如何排序?
        Student[] students = new Student[4];
        students[0] = new Student("张三",20,178);
        students[1] = new Student("小美",24,166);
        students[2] = new Student("李四",22,183);
        students[3] = new Student("李华",22,155);

//        Arrays.sort(students);
//        System.out.println(Arrays.toString(students));  //报错 ClassCastException异常 不能直接用sort比较对象数组

        System.out.println(Arrays.toString(students));
        //方式1:让Student类实现Comparable(比较规则)接口,然后重写compareTo方法来指定比较规则
//        Arrays.sort(students);
//        System.out.println(Arrays.toString(students));

        //方式2:使用下面这个sort方法,创建Comparator比较器接口的匿名内部类对象,然后自己制定比较规则
        Arrays.sort(students, new Comparator<Student>() {  //匿名内部类
            @Override
            public int compare(Student o1, Student o2) {
                //制定比较规则:左边对象o1 右边对象o2
                //按照身高升序排列
//                if(o1.getHeight() > o2.getHeight()){
//                    return 1;
//                }else if(o1.getHeight() < o2.getHeight()){
//                    return -1;
//                }else{
//                    return 0;
//                }
                //上述代码可以简化 按照身高升序排列
                return Double.compare(o1.getHeight(),o2.getHeight());

                //不要直接return o1.getHeight()-o2.getHeight()
                //因为返回值要求是int,这里身高是double
                //用强制转换的话,可能会导致结果出错(如o1身高178.1,o2身高178,178.1-178=0.1,强转后变成0,结果变成两人一样高)

                //按照身高降序排列
//                return Double.compare(o2.getHeight(),o1.getHeight());
            }
        });
        System.out.println(Arrays.toString(students));
    }
}

//Student
public class Student implements Comparable<Student>{
    private String name;  //姓名
    private int age;  //年龄
    private double height;  //身高

    //指定比较规则(假设这里的比较规则是按照年龄升序排序)
    //this是比较者 o是被比较者
    @Override
    public int compareTo(Student o) {
        //约定:如果认为左边对象大于右边对象,返回任意正整数
        //约定:如果认为左边对象小于右边对象,返回任意负整数
        //约定:如果认为左边对象等于右边对象,返回0
//        if(this.age > o.age){
//            return 1;
//        }else if(this.age < o.age){
//            return -1;
//        }else{
//            return 0;
//        }

        //上述代码可以简化
//        return this.age - o.age;  //升序
        return o.age - this.age;  //降序
    }

    public Student() {
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

四. JDK8新特性:Lambda表达式

        Lambda表达式是JDK 8开始新增的一种语法形式:作用是用于简化匿名内部类的代码写法

注意:

    · Lambda表达式只能简化函数式接口的匿名内部类!!!(什么是函数式接口?有且仅有一个抽象方法的接口就是函数式接口)

    · 大部分函数式接口上面都可能会有一个@FunctionalInterface的注解,有该注解的接口必定是函数式接口

格式:

(被重写方法的形参列表)-> {

        被重写方法的方法体代码

}

//demo
public class demo {
    public static void main(String[] args) {
        Animal a = new Animal(){
            @Override
            public void run() {
                System.out.println("小狗跑跑跑");
            }
        };
        a.run();

        //注意:Lambda表达式并不能简化全部匿名内部类的写法,只能简化函数式接口的匿名内部类
        //上述代码不是接口,因此不能被简化(下面代码是错误示范)
//        Animal a = () -> {
//            System.out.println("小狗跑跑跑");
//        }

//        Swimming s = new Swimming(){
//            @Override
//            public void swim() {
//                System.out.println("学生在游泳");
//            }
//        };
//        s.swim();

        Swimming s = () -> {
            System.out.println("学生在游泳");
        };
        s.swim();
    }
}

interface Swimming{
    void swim();
}

abstract class Animal{
    public abstract void run();
}

Lambda表达式的省略规则(进一步简化Lambda表达式的写法)

· 参数类型可以省略不写

· 如果只有一个参数,参数类型可以省略,同时()也可以省略

· 如果Lambda表达式中的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!此时,如果这行代码是return语句,也必须去掉return不写

五. JDK8新特性:方法引用

        进一步简化Lambda表达式的

        方法引用的标志性符号“::”

5.1 静态方法的引用

        类名::静态方法

使用场景

        如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用

5.2 实例方法的引用

        对象名::实例方法

使用场景

        如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用

public class demo{
    public static void main(String[] args){
        Student[] students = new Student[4];
        students[0] = new Student("张三",20,178);
        students[1] = new Student("小美",24,166);
        students[2] = new Student("李四",22,183);
        students[3] = new Student("李华",22,155);

        //原始写法
//        Arrays.sort(students, new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                return o1.getAge() - o2.getAge(); //按照年龄升序排列
//            }
//        });

        //使用Lambda进行简化后的形式
        //Arrays.sort(students, (o1,o2) -> o1.getAge() - o2.getAge());

        //Arrays.sort(students, (o1,o2) -> CompareByData.compareByAge(o1,o2));
        //方法引用(静态方法的引用)
        Arrays.sort(students, CompareByData::compareByAge);
        System.out.println(Arrays.toString(students));

        System.out.println("=================================");

        //原始写法
//        Arrays.sort(students, new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                return o2.getAge() - o1.getAge(); //按照年龄降序排列
//            }
//        });

        //使用Lambda进行简化后的形式
        Arrays.sort(students, (o1, o2) -> o2.getAge() - o1.getAge());  //降序

        CompareByData compareByData = new CompareByData();
        //Arrays.sort(students, (o1,o2) -> compareByData.compareByAgeDesc(o1,o2));
        //实例方法的引用
        Arrays.sort(students, compareByData::compareByAgeDesc);

        System.out.println(Arrays.toString(students));
    }
}

//CompareByData
public class CompareByData {
    //静态方法
    public static int compareByAge(Student o1,Student o2){
        return o1.getAge() - o2.getAge(); //升序排序规则
    }
    //实例方法
    public int compareByAgeDesc(Student o1,Student o2){
        return o2.getAge() - o1.getAge(); //降序排序规则
    }
}

//Student类 参考Arrays里面的代码

5.3 特定类型方法的引用

        类型::方法

使用场景

        如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用

//demo
public class demo{
    public static void main(String[] args){
        String[] names = {"boby","angela","Andy","dlei","caocao","Babo","jack","Cici"};
        //进行排序(默认是按照字符串的首字符编号进行)
        Arrays.sort(names);  [Andy, Babo, Cici, angela, boby, caocao, dlei, jack]

        //要求忽略首字符大小写进行排序
//        Arrays.sort(names, new Comparator<String>() {
//            @Override
//            public int compare(String o1, String o2) {
//                //指定比较规则: 如o1=Andy o2=angela
//                return o1.compareToIgnoreCase(o2);
//            }
//        });

        //Lambda简化
//        Arrays.sort(names, (o1, o2) -> o1.compareToIgnoreCase(o2));
        //特定类型方法的引用
        Arrays.sort(names, String::compareToIgnoreCase);

        System.out.println(Arrays.toString(names));
    }
}

5.4 构造器引用

        类型::new

使用场景

        如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用

//demo
public class demo{
    public static void main(String[] args){
        //创建接口的匿名内部类
//        createCar cc = new createCar() {
//            @Override
//            public Car create(String name, double price) {
//                return new Car(name,price);
//            }
//        };

        //Lambda简化
//        createCar cc = (name, price)-> new Car(name,price);

        //构造器引用
        createCar cc = Car::new;

        Car c = cc.create("奔驰",49.9);
        System.out.println(c);
    }
}

interface createCar{
    Car create(String name,double price);
}

//Car
public class Car {
    private String name;
    private double price;

    public Car() {
    }

    public Car(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 "Car{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值