Java数据结构准备工作---常用类


前言

上一节课我们学习时间复杂度和空间复杂度。今天我们学习常用类
在这里插入图片描述
这个就是我们要学习的内容


1.包装类

1.1.包装类基本知识

Java 是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。比如:将基本数据类型存储到 Object[ ]数组或集合中的操作等等。为了解决这个不足, Java 在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。
包装类位于 java.lang 包,八种包装类和基本数据类型的对应关系:
在这里插入图片描述
在这八个类名中,除了 Integer 和 Character 类以外,其它六个类的类名和基本数
据类型一致,只是类名的第一个字母大写而已
Number 类是抽象类,因此它的抽象方法,所有子类都需要提供实现。 Number 类提供了
抽象方法: intValue()、 longValue()、 floatValue()、 doubleValue(),意味着所有的“数
字型”包装类都可以互相转型。

1.2.包装类的用途

对于包装类来说,这些类的用途主要包含两种:

  1. 作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如 Object[ ]、集合等
    的操作。
  2. 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法(这些操
    作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化!)。

1.3.装箱和拆箱

装箱(autoboxing)和拆箱(unboxing):将基本数据类型和包装类自动转换。

1.3.1.装箱:

public static void main(String[] args) {
        int a=10;
        Integer b=new Integer(a);//这个方法在JDK9之后就不再使用了,但是为了兼用之前的版本,但是也可以使用
        Integer c=Integer.valueOf(a);
        Integer d=a;
    }

这个是装箱操作,其中

Integer c=Integer.valueOf(a);是显示装箱
Integer b=new Integer(a);或者Integer d=a;是自动转型
他的底层仍是使用的是Integer.valueOf()方法

可以看反汇编

1.3.2.拆箱

 public static void main(String[] args) {
        Integer a=10;
        int b= a.intValue();
        int c=a;
    }

这个就是拆箱操作。
自动装箱/拆箱的本质是:
自动装箱与拆箱的功能是编译器来帮忙,编译器在编译时依据您所编写的语法,决定是否进行装箱或拆箱动作。
自动装箱与拆箱的功能是所谓的“编译器蜜糖(Compiler Sugar)”,虽然使用这个功能很方
便,但在程序运行阶段您得了解 Java 的语义。 如下所示的程序是可以通过编译的:

public static void main(String[] args) {
        Integer a=null;
        int i=a;
        System.out.println(i);
    }

在这里插入图片描述
我们会发现报错了,空指针异常,为什么?
因为包装类是属于引用类型,会在栈和堆上开辟内存,a的值可以是null,但是在进行拆箱的时候,i是一个基本数据类型,不可能是null,因而报错。

1.4 包装类的缓存问题

我们看一个例子

public static void main(String[] args) {
        Integer a=100;
        Integer b=100;
        System.out.println(a==b);
        Integer c=1000;
        Integer d=1000;
        System.out.println(c==d);
    }

大家觉得分别输出什么?
在这里插入图片描述
为什么呢?
整型、 char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓
存处理,其目的是提高效率。
缓存原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每
个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程
发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取
数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法
来创建对象。
我们再看看Integer的部分源码
在这里插入图片描述
这段代码中我们需要解释下面几个问题:

  1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用。
  2. 一般情况下 IntegerCache.low为-128, IntegerCache.high为127。

我们可以发现,如果-128<=i<127的话,会存放在IntegerCache.cache数组当中,那么在上面的代码中,100指的是同一个对象,但是如果不在这个范围的话,就是new Ineger()一个对象,会在栈和堆上开辟内存,那么用两个1000所在地址不一样,那么就不能使用==,而要使用equals方法了。

总结
1.自动装箱调用的是 valueOf()方法,而不是 new Integer()方法。
2.自动拆箱调用的 xxxValue()方法。
3.包装类在自动装箱时为了提高效率,对于-128~127 之间的值会进行缓存处理。超过范
围后,对象之间不能再使用==进行数值的比较,而是使用 equals 方法。
下面我们模拟复现一个Integer类,叫做MyInteget类

public class MyInteger {
    private int value;
    private static MyInteger[]cache=new MyInteger[256];
    public static final int LOW=-128;
    public static final int HIGH=127;
    private MyInteger(int i){
        this.value=i;
    }
    //静态代码块先被执行
    static {
        for(int i=MyInteger.LOW;i<=HIGH;i++){
            cache[i+128]=new MyInteger(i);
        }
    }
    public int intValue(){
        return this.value;
    }
    public static MyInteger ValueOf(int i){
        if(i>=LOW&&i<=HIGH){
            return cache[i+128];
        }
        return new MyInteger(i);
    }

    @Override
    public String toString() {
        return this.value+"";
    }

    public static void main(String[] args) {
        MyInteger i=MyInteger.ValueOf(10);
        MyInteger a=MyInteger.ValueOf(1000);
        System.out.println(i);
        System.out.println(a);
    }
}

String类型咱们在Java(十一)—String类型中已经讲过了,因此在这就不在进行赘述了。

2.时间处理类

时间如流水,一去不复返”,时间是一维的。所以,我们需要一把刻度尺来表达和度
量时间。在计算机世界,我们把 1970 年 1 月 1 日 00:00:00 定为基准时间,每个度量单
位是毫秒(1 秒的千分之一),如图所示。
在这里插入图片描述
我们用 long 类型的变量来表示时间,从基准时间前后几亿年都能表示。
这个“时刻数值” 是所有时间类的核心值,年月日都是根据这个“数值” 计算出来的。
我们工作学习涉及的时间相关类有如下这些在这里插入图片描述

2.1.Date 时间类(java.util.Date)

在标准 Java 类库中包含一个 Date 类。它的对象表示一个特定的瞬间,精确到毫秒。

  1. Date() 分配一个 Date 对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒)。
  2. Date(long date) 分配 Date 对象并初始化此对象,以表示自从标准基准时间以来的毫秒数。
  3. boolean equals(Object obj) 比较两个日期的相等性。
  4. long getTime() 返回毫秒数。
  5. String toString() 把此 Date 对象转换为以下形式的 String:
    dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天
public static void main(String[] args) {
        long nowNum=System.currentTimeMillis();
        System.out.println(nowNum);
        Date date1=new Date(10000020323L);
        Date date2=new Date();
        System.out.println(date1);
        System.out.println(date1.getTime());
        System.out.println(date2);
        System.out.println(date2.getTime());

        Date date3=new Date(-21L*365*24*3600*1000);//1949 年
        System.out.println(date3);
        System.out.println(date3.equals(date1));
        System.out.println(date3.before(date1));
        System.out.println(date3.after(date1));
    }

2.2.DateFormat 类和 SimpleDateFormat 类

DateFormat 类的作用:
把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。
DateFormat 是一个抽象类,一般使用它的的子类SimpleDateFormat 类来实现。

public static void main(String[] args)throws ParseException {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String str="2024-6-8 12:25:00";
        Date date=format.parse(str);//从给定字符串的开头解析文本以生成日期。
        System.out.println(date.getTime());
        System.out.println(date);
        System.out.println("=========");
        DateFormat dateFormat=new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒");
        Date date1=new Date(2342342342334L);
        String date1Str=format.format(date1);//将 Date 格式化为日期时间字符串。
        System.out.println(date1Str);

        //小妙招
        Date now = new Date();
        DateFormat f1 = new SimpleDateFormat("今年的第D天,第w周");
        String str3 = f1.format(now);
        System.out.println(str3);
    }

2.3.Calendar 日历类

Calendar 类是一个抽象类,为我们提供了关于日期计算的功能,比如:年、月、日、时、分、秒的展示和计算。
GregorianCalendar 是 Calendar 的子类, 表示公历。

注意:
月份的表示,一月是 0,二月是 1,以此类推, 12 月是 11。 因为大多数人习惯于使用单词而不是使用数字来表示月份,这样程序也许更易读,父类 Calendar 使用常量来表示月份:
JANUARY、 FEBRUARY 等等

import java.util.GregorianCalendar;
import java.util.*;
public class TestCalendar {
    public static void main(String[] args) {
        GregorianCalendar calendar=new GregorianCalendar
                (2024,6,8,12,40,00);
        System.out.println(calendar);
        int year=calendar.get(Calendar.YEAR);
        int month=calendar.get(Calendar.MONTH);
        int day=calendar.get(Calendar.DAY_OF_MONTH);
        int day2=calendar.get(Calendar.DATE);
        // 日:Calendar.DATE和Calendar.DAY_OF_MONTH同义
        int date = calendar.get(Calendar.DAY_OF_WEEK);
        // 星期几 这里是:1-7.周日是1,周一是2,。。。周六是7
        System.out.println(year);
        System.out.println(month);
        System.out.println(day);
        System.out.println(day2);
        System.out.println(date);

        //设置日期
        GregorianCalendar calendar1=new GregorianCalendar();
        calendar1.set(Calendar.YEAR,2000);
        calendar1.set(Calendar.MONTH,1);
        calendar1.set(Calendar.DATE,25);
        calendar1.set(Calendar.HOUR_OF_DAY,8);
        calendar1.set(Calendar.MINUTE,10);
        calendar1.set(Calendar.SECOND,10);

        //日期的计算
        GregorianCalendar calendar2=new GregorianCalendar
                (2024,6,8,12,40,00);
        calendar2.add(Calendar.MONTH,-7);
        calendar2.add(Calendar.DATE,7);
        printCalendar(calendar2);
        // 日历对象和时间对象转化
        Date d = calendar2.getTime();
        GregorianCalendar calendar4 = new GregorianCalendar();
        calendar4.setTime(new Date());
    }
    static void printCalendar(Calendar calendar) {
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int date = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 星期几
        String week = "" + ((date == 0) ? "日" : date);
        int hour = calendar.get(Calendar.HOUR);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        System.out.printf("%d年%d月%d日,星期%s %d:%d:%d\n", year, month, day,
                week, hour, minute, second);
    }
}

3.其他常用类

3.1.Math类

java.lang.Math 提供了一系列静态方法用于科学计算; 常用方法如下:
 abs 绝对值
 acos,asin,atan,cos,sin,tan 三角函数
 sqrt 平方根
 pow(double a, double b) a 的 b 次幂
 max(double a, double b) 取大值
 min(double a, double b) 取小值
 ceil(double a) 大于 a 的最小整数
 floor(double a) 小于 a 的最大整数
 random() 返回 0.0 到 1.0 的随机数
 long round(double a) double 型的数据 a 转换为 long 型(四舍五入)
 toDegrees(double angrad) 弧度->角度
 toRadians(double angdeg) 角度->弧

public static void main(String[] args) {
        //取整相关操作
        System.out.println(Math.ceil(3.2));
        System.out.println(Math.floor(3.2));
        System.out.println(Math.round(3.2));
        System.out.println(Math.round(3.8));
        //绝对值、开方、a的b次幂等操作
        System.out.println(Math.abs(-45));
        System.out.println(Math.sqrt(64));
        System.out.println(Math.pow(2,5));
        System.out.println(Math.pow(5,2));
        //Math类中常用的常量
        System.out.println(Math.PI);
        System.out.println(Math.E);
        //随机值
        System.out.println(Math.random());//[0,1)
    }

3.2.Random 类

Random 类: 专门用来生成随机数

public static void main(String[] args) {
        Random random=new Random();
        //随机产生[0,1)的double的数据
        System.out.println(random.nextDouble());
        //随机生成int范围内的数据
        System.out.println(random.nextInt());
        //随机生成一个[0,1)范围内的数据
        System.out.println(random.nextFloat());
        //随机生成false或true
        System.out.println(random.nextBoolean());
        //随机生成一个[0,10)int类型的数据
        System.out.println(random.nextInt(10));
        //随机生成一个[20,30)的数字
        System.out.println(20+random.nextInt(10));
        System.out.println(20+(int)(random.nextDouble()*10));
    }

注意
Random 类位于 java.util 包下。

3.3. File 类

File 类的基本用法:
java.io.File 类: 代表文件和目录, 用于: 读取文件、 创建文件、删除文件、修改文件。
【示例】使用 File 类创建文件
File 类的常见构造方法: public File(String pathname)
以 pathname 为路径创建 File 对象,如果 pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储

public static void main(String[] args)throws IOException {
        System.out.println(System.getProperty("user.dir"));//当前文件所在的位置
        File f=new File("a.txt");//相对路径,默认放在uesr.dir目录下
        f.createNewFile();//创建文件
    }

在这里插入图片描述
user.dir 就是本项目的目录。 上面代码执行后,在本项目和 D 盘下都生成了新的文件。
在这里插入图片描述
这个是绝对路径
通过 File 对象可以访问文件的属性:
在这里插入图片描述

public static void main(String[] args) throws IOException {
        File f=new File("a.txt");//相对路径,默认放在uesr.dir目录下
        f.createNewFile();//创建文件
        System.out.println("File f是否存在:"+f.exists());
        System.out.println("File f是否是目录:"+f.isDirectory());
        System.out.println("File f是否是文件:"+f.isFile());
        System.out.println("File f的最后修改时间"+f.lastModified());
        System.out.println("FIle f的大小:"+f.length());
        System.out.println("File f的文件名:"+f.getName());
        System.out.println("File f的文件目录路径"+f.getPath());
    }

通过 File 对象创建空文件或目录(在该对象所指的文件或目录不存在的情况下)
在这里插入图片描述
使用 mkdir 创建目录

public static void main(String[] args)throws IOException {
        //使用 mkdir 创建目录
        File f=new File("d:/c.txt");
        f.createNewFile();
        f.delete();
        File f2=new File("d:/电影/华语/大陆");
        boolean flag=f2.mkdir();//目录结构中有一个不存在,则不会创建整个目录树
        System.out.println(flag);//创建失败
    }

使用 mkdirs 创建目录

public static void main(String[] args) {
        File f3=new File("d:/电影/华语/大陆");
        boolean flag=f3.mkdirs();//目录结构中有一个不存在也没关系;创建整个目录树
        System.out.println(flag);//创建成功
    }

3.4 递归遍历目录结构和树状展现

本节结合前面给大家讲的递归算法,展示目录结构。大家可以先建立一个目录,下面增加几个子文件夹或者文件,用于测试。

public static void PrintFile(File file,int level){
        for(int i=0;i<level;i++){
            System.out.print('-');
        }
        //输出文件名
        System.out.println(file.getName());
        if(file.isDirectory()){
            File[]files=file.listFiles();
            for (File temp:files){
                PrintFile(temp,level+1);
            }
        }
    }
    public static void main(String[] args) throws IOException {
        File f1=new File("d:/电影/华语/大陆/哪吒传奇.mp4");
        File f2=new File("d:/电影/华语/大陆/战狼.mp4");
        File f3=new File("d:/电影/华语/大陆/战狼2.mp4");
        f1.createNewFile();
        f2.createNewFile();
        f3.createNewFile();
        File f4=new File("d:/电影/好莱坞/速度与激情8.mp4");
        boolean flag=f4.mkdirs();
        System.out.println(flag);
        File f=new File("d:/电影");
        PrintFile(f,0);
    }

在这里插入图片描述

3.5.枚举

JDK1.5 引入了枚举类型。枚举类型的定义包括枚举声明和枚举体

格式如下:
enum 枚举名 {
枚举体(常量列表)
}

枚举体就是放置一些常量。我们可以写出我们的第一个枚举类型,如示例所示:

import java.util.Random;

/**
 * @Author: Lenovo
 * @Date: 2024/6/8 15:19
 * @description:
 */
enum Season{
    SPRING,SUMMER,AUTUMN,WINTRE
}
class Jijie{
    public static final int SPRING=0;
    public static final int SUMMER=1;
    public static final int AUTUMN=2;
    public static final int WINTER=3;
}

public class TestEnum {

    public static void main(String[] args) {
        /*System.out.println(Jijie.SPRING);
        System.out.println(Season.SPRING);*/
        for(Season s:Season.values()){
            System.out.println(s);
        }
        int a=new Random().nextInt(4);
        switch (Season.values()[a]){
            case SPRING:
                System.out.println("春天");
                break;
            case SUMMER:
                System.out.println("夏天");
                break;
            case AUTUMN:
                System.out.println("秋天");
                break;
            case WINTRE:
                System.out.println("冬天");
                break;
        }
    }

}

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值