07-Java基础-常见类库

常见类库

String类简介

String类不能被继承

通过源码可以看到String类前面加了final修饰,因此String类是不能够被继承的。将其设置为不能被继承的原因是为了减少歧义。

字符串(String)的不可变性

String创建好之后值是不可以被改变的,这里指的是在堆中的字符串的值是不可以被改变。

示例:

/*
    String是不能被改变的
 */
public class String02 {
    public static void main(String[] args) {
        String s = "monkey";
        change(s);
        System.out.println("main:" + s);//monkey
    }

    public static void change(String s) {
        s = "good";
        System.out.println("change:" + s);
    }
}

String是引用数据类型,但是这里作为方法参数传递的时候,效果跟基本数据类型是一样的。也就是说在堆中创建出来的字符串”monkey”是不能被改变的,如果要修改,系统会在堆中重新开辟内存空间将”good”放入,然后将change方法中的s重新引用这个新的内存地址上的”good”。
String不可变的主要原因是其底层使用了一个final修饰的byte数组(jdk9之后版本中),final修饰的变量是不能被改变的。在jdk8版本中,String底层使用的是final修饰的char数组。这个版本之间的变化。

image-20230706150633228

字符串常量池

我们声明的字符串会放到一个叫做字符串常量池的地方,这样可以减少内存的使用,字符串常量池是堆的一部分。

    String s1 = "monkey";//这种写法会利用字符串常量池,减少内存的使用
    String s2 = "monkey";
    String s3 = new String("monkey");
    String s4 = new String("good");


    System.out.println(s1 == s2);//true s1和s2的内存地址相同
    System.out.println(s1 == s3);//false
    System.out.println(s1.equals(s3));//true

上面代码中,创建s1时,字符串常量池中还不存在堆中monkey的引用,因此jvm会在常量池中创建一个引用指向堆中的这个字符串对象,创建s2时,jvm会去常量池中搜索,此时常量池中有monkey的引用,所以就不创建了,直接让s2指向之前创建的monkey,所以s1和s2指向的是同一个堆内存中的对象。
创建s3时,因为使用了new关键字,所以会在堆中开辟一块内存地址将其放入,s3指向这个新的内存地址,所以s3和s1指向的不是同一个内存地址。
创建s4时,使用了new关键字,会在堆中开辟一块内存地址,s4指向这个内存地址,然后字符串常量池中没有指向good的引用,所以会再重新开辟一块空间,将good放入,然后在字符串常量池中指向这个地址。

开发中建议使用String s = “monkey1024”;这种方式创建字符串对象,可以减少堆内存的使用。
注意:比较两个字符串是否一致最好使用equals方法

image-20230706151126679

String类常用方法

  1. char charAt(int index);获取index位置的字符

  2. boolean contains(CharSequence s);判断字符串中是否包含某个字符串

  3. boolean endsWith(String endStr);判断是否是以某个字符串结尾

  4. boolean equalsIgnoreCase(String anotherString);忽略大小写比较两个字符串是否相等

  5. byte[] getBytes();转换成byte数组

  6. int indexOf(String str);取得指定字符在字符串的位置

  7. int indexOf(String str, int fromIndex);从指定的下标开始取得指定字符在字符串的位置

  8. int lastIndexOf(String str);从后面开始取得指定字符在字符串最后出现的的位置

  9. int length();获取字符串的长度

  10. String replaceAll(String s1,String s2);替换字符串中的内容

  11. String[] split(String s);根据指定的表达式拆分字符串

  12. boolean startsWith(String s);判断是否是以某个字符串开始

  13. String substring(int begin);根据传入的索引位置截子串

  14. String substring(int beginIndex, int endIndex);根据传入的起始和结束位置截子串

  15. char[] toCharArray();将字符串转换为char数组

  16. void toUpperCase();转换为大写

  17. void toLowerCase();转换为小写

  18. String trim();去除首尾空格

  19. String valueOf(Object obj);将其他类型转换为字符串类型

        String s1 = "monkey1024";
        // char charAt(int index);获取index位置的字符
        System.out.println(s1.charAt(5));
        // boolean contains(CharSequence s);判断字符串中是否包含某个字符串
        System.out.println(s1.contains("key"));
        // boolean endsWith(String endStr);判断是否是以某个字符串结尾
        System.out.println(s1.endsWith("1028"));
        // boolean equalsIgnoreCase(String anotherString);忽略大小写比较两个字符串是否相等
        System.out.println(s1.equalsIgnoreCase("Monkey1024"));
        // byte[] getBytes();转换成byte数组
        String s2 = "abc";
        byte[] b1 = s2.getBytes();
        for(int i=0; i<b1.length; i++){
            System.out.print(b1[i] + " ");
        }
        System.out.println();
        // int indexOf(String str);取得指定字符在字符串的位置
        System.out.println(s1.indexOf("y"));
        // int indexOf(String str, int fromIndex);从指定的下标开始取得指定字符在字符串的位置
        String s3 = "monkey1024monkeyy";
        System.out.println(s3.indexOf("y", 6));
        // int lastIndexOf(String str);从后面开始取得指定字符在字符串最后出现的的位置
        System.out.println(s3.lastIndexOf("y"));
        // int length();获取字符串的长度
        System.out.println(s3.length());
        // String replaceAll(String s1,String s2);替换字符串中的内容
        String s4 = "monkeymonkey1024monkey";
        System.out.println(s4.replaceAll("key", "YYY"));
        // String[] split(String s);根据指定的表达式拆分字符串
        String s5 = "a,b,c,d";
        String[] array1 = s5.split(",");
        for(int i=0; i<array1.length; i++){
            System.out.print(array1[i] + " ");
        }
        System.out.println();
        // boolean startsWith(String s);判断是否是以某个字符串开始
        System.out.println(s3.startsWith("m1"));
        // String substring(int begin);根据传入的索引位置截子串
        System.out.println(s3.substring(5));
        // String substring(int beginIndex, int endIndex);根据传入的起始和结束位置截子串
        System.out.println(s3.substring(6, 10));
        // char[] toCharArray();将字符串转换为char数组
        char[] array2 = s5.toCharArray();
        for(int i=0; i<array2.length; i++){
            System.out.print(array2[i] + " ");
        }
        System.out.println();
        // void toUpperCase();转换为大写
        System.out.println(s5.toUpperCase());
        // void toLowerCase();转换为小写
        System.out.println(s5.toLowerCase());
        // String trim();去除首尾空格
        String s6 = " java good ok ";
        System.out.println(s6.trim());
        // String valueOf(Object obj);将其他类型转换为字符串类型
        Object o = new Object();
        o = null;
        System.out.println(String.valueOf(o));//建议使用这种方法转换字符串
        //System.out.println(o.toString());//报出空指针错误
    

debug的使用

debug简介

通过debug功能可以方便程序员一步一步的观察程序运行中的数据变化。在很多集成开发环境中都有提供,比如IDEA,eclipse,myeclipse。

debug的作用:

  • 可以帮助程序员快速定位问题
  • 帮助程序员快速上手代码

debug的使用

首先在代码的某一行上添加断点,然后在idea中使用debug运行,就会出现下面的界面,里面的按钮我做了标号,下面有对应的解释

image-20230706151221573
  1. show execution point

    快速定位到当前程序执行的位置

  2. step over(F8)

    让程序执行到下一行

  3. step into(F7)

    进入到方法中执行

  4. force step into(alt shfit f7)

    强制进入到方法中执行,适合进入第三方编写的方法当中

  5. step out(shift F8)

    跳出方法,在debug进入到某个方法中的时候可以跳出方法

  6. drop frame

    多次进出方法,当debug某个方法运行一部分之后,希望该方法再次进入debug,可以使用该按钮

  7. run to curser(alt F9)

    快速执行到当前光标所在的位置

  8. evaluate expression(alt F8)

    运行一些简短的代码,方便我们在debug的时候查看

  9. trace current stream chain

    在debug Stream流部分代码的时候可以帮助我们看到数据的变化

image-20230706151250678
  1. rerun(alt F5)

    重新以debug方式运行

  2. resume program(F9)

    如果当前代码后面有断点则执行到下个断点所在的位置,否则程序运行结束

  3. pause program

    当程序以debug运行且执行到某个比较耗时操作的时候,点击按钮,会进入到debug模式运行程序

  4. stop program(ctrl F2)

    停止程序

  5. view breakpoint (ctrl shift F8)

    查看所有断点

  6. mute breakpoint

    断点全部失效/生效

  7. get thread dump

    查看线程的状态

  8. restore layout

    恢复debug布局

  9. settings

    设置

通过下面代码进行debug的演示

import java.util.ArrayList;
import java.util.Arrays;


/*
    IDEA中的debug断点调试功能
 */
public class DebugTest01 {
    public static void main(String[] args) throws InterruptedException {
        int addResult = add();
        int subtractResult = subtract();

        System.out.println(addResult);
        System.out.println(subtractResult);

        Object o1 = new Object();
        Object o2 = new Object();

        //shift + f7 智能步入,进入到我们指定的方法中
        System.out.println(o1.equals(o2));


    }

    public static int add() {
        int a = 10;
        int b = 15;
        int c = a + b;
        return c;
    }

    public static int subtract() {
        int a = 30;
        int b = 45;
        int c = a - b;
        return c;
    }


}

正则表达式简介

正则表达式简介

有的地方也叫做规则表达式,通过正则可以将符合某种规则的字符串匹配出来,比如要将"monkey1024study1j2a3v4a"这个字符串中的数字替换为"中",可以使用正则表达式匹配数字,然后进行替换即可,正则表达式是一门独立的学科,这里这是简单介绍一下,以后在工作中用到的时候,可以去网上查。
“^m{2}$” 表示 2个m字符.等同于 “mm”
\d 表示数字
\D 表示非数字
\w 表示英文字母
\W 表示非英文字母

除了这些还有很多,工作中常用的有
匹配邮箱格式:\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+.)+[A-Za-z]{2,14}
匹配手机号:0?(13|14|15|18)[0-9]{9}

System.out.println("mm".matches("^m{2}$"));    

String s1 = "monkey1024study1j2a3v4a";
//将数字替换为"中"
System.out.println(s1.replaceAll("\\d", "中"));
//匹配手机号
System.out.println("15188888888".matches("0?(13|14|15|18)[0-9]{9}"));
//匹配邮箱
System.out.println("monkey@monkey1024.com".matches("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}"));

String相关练习题

String练习题

  1. 字符串反转,例如将"abc"变成"cba"
  2. 统计一个字符串里面另一个字符串出现的次数,例如统计"monkey"在"I am monkey1024.monkey like banana.little monkey is smart."中出现的次数
  3. 统计一个字符串中大写字母出现的次数

答案

1.思路:字符串是由多个字符组成的,可以将字符串转换为字符(char)数组,然后倒序遍历数组即可

package com.monkey1024.string;

import java.util.Scanner;

/**
 * 字符串反转
 *
 */
public class Exercise01 {

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        String input = s.next();
        //将输入的字符串转换为char类型数组
        char[] charArray = input.toCharArray();
        //遍历数组并倒着输出
        for(int i=charArray.length-1; i>=0; i--){
            System.out.print(charArray[i]);
        }
    }

}

2.思路:通过indexOf方法在大的字符串中查找小字符串的索引值,找到后将这个索引值和小字符串的长度相加,之后将大的字符串截取根据相加的结果截取子串,然后继续在剩下的字符串中查找小字符串的索引值,直到索引值返回-1为止

package com.monkey1024.string;


/**
 * 统计一个字符串里面另一个字符串出现的次数
 *
 */
public class Exercise02 {

    public static void main(String[] args) {
        String src = "I am monkey1024.monkey like banana.little monkey is smart.";
        String dest = "monkey";
        //定义出现的次数
        int count = 0;

        //定义索引值
        int index = 0;


        while((index = src.indexOf(dest)) != -1){
            count++;
            //将src截取子串
            src = src.substring(index + dest.length());
        }

        System.out.println("出现的次数是:" + count);
    }

}

3.思路:每个大写字母都是一个字符char,而大写字母A~Z是有范围的,只要统计这个范围内的字符即可

package com.monkey1024.string;


public class Exercise03 {

    public static void main(String[] args) {
        String src = "monkEY";
        //统计大写字母出现的次数
        int count = 0;

        //将字符串转换为字符数组
        char[] c = src.toCharArray();
        for(int i=0; i<c.length; i++){
            //判断是否为大写字母
            if(c[i] >= 'A' && c[i] <= 'Z'){
                count++;
            }
        }

        System.out.println("大写字母出现的次数:" + count);
    }

}

StringBuffer和StringBuilder

StringBuffer简介

不要频繁的对字符进行拼接操作,例如下面代码:

     String str = "";

    for (int i = 0; i < 100; i++) {
        str += i;//str = str + i; 造成内存空间的浪费
    }

    System.out.println(str);

每次对字符串修改,底层都会重新开辟新的堆内存空间,这样会开辟很多个空间地址,造成浪费。

如果需要对字符串进行频繁拼接的话,建议使用StringBuffer或者StringBuilder,两者的使用方法一致,下面以StringBuffer为例说明。

StringBuffer是一个字符串缓冲区,如果需要频繁的对字符串进行拼接时,建议使用StringBuffer。
工作原理
StringBuffer的底层是byte数组(jdk9之后),jdk8中底层是char数组,如果没有明确设定,则系统会默认创建一个长度为16的byte类型数组,在使用时如果数组容量不够了,则会通过数组的拷贝对数组进行扩容,所以在使用StringBuffer时最好预测并手动初始化长度,这样能够减少数组的拷贝,从而提高效率。

String与StringBuffer的区别?
String是不可变字符序列,存储在字符串常量池中
StringBuffer的底层是byte数组,系统会对该数组进行扩容

如何使用StringBuffer进行字符串拼接?

    //创建对象
    //StringBuffer sb = new StringBuffer();//底层会创建一个长度是16的byte数组
    StringBuffer sb = new StringBuffer(300);//底层会创建一个长度是300的byte数组,对数据长度进行预估

    for (int i = 0; i < 100; i++) {
        sb.append(i);//拼接操作
    }

    System.out.println(sb);

StringBuilder和StringBuffer的区别

通过API可以看到StringBuilder和StringBuffer里面的方法是一样的,那他们有什么区别呢?
StringBuffer是jdk1.0版本中加入的,是线程安全的,效率低
StringBuilder是jdk5版本加入的,是线程不安全的,效率高

基本类型和包装类

包装类

什么是包装类?
Java里面8个基本数据类型都有相应的类,这些类叫做包装类。
包装类有什么优点
可以在对象中定义更多的功能方法操作该数据,方便开发者操作数据,例如基本数据类型和字符串之间的转换。
基本数据类型和对应的包装类

包装类都在java.lang包里面

基本数据类型         包装类
    byte 			Byte
    short			Short
    int				Integer
    long			Long
    float			Float
    double			Double
    char			Character
    boolean			Boolean

下面以Integer为例来学习一下包装类,Integer底层实际上就是一个final修饰的int成员变量。
获取int类型的最小值:

Integer.MIN_VALUE

获取int类型的最大值:

Integer.MAX_VALUE

创建Integer对象:
1.传入int类型,会将int类型的10转换为Integer类型,该构造方法已被废弃:

Integer i1 = new Integer(10); 

2.传入String类型,会将String类型的”1024″转换为Integer类型,注意:如果传入的字符串不是数字,将会报出NumberFormatException。该构造方法已被废弃。

Integer i2 = new Integer("1024");

3.自动装箱,把基本类型转换为包装类类型,推荐使用

Integer i3 = 1024;

除此之外还有自动拆箱,可以将Integer类型的变量直接赋值给int类型:

Integer i4 = 1024;
int i5 = i4

将String类型转换为int类型,传入的字符串必须是数字字符串:

int i6 = Integer.parseInt("10");

将String类型转换为Integer类型:

Integer i7 = Integer.valueOf("10");

将int类型的十进制转换成2进制:

String s1 = Integer.toBinaryString(10);

将int类型的十进制转换成16进制:

String s2 = Integer.toHexString(10);

将int类型的十进制转换成8进制:

String s3 = Integer.toOctalString(10);

注意:Integer是引用数据类型,在判断两个Integer类型是否相等时,要使用equals方法,不能使用”==”,Integer已经重写了Object中的equals方法。

Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3==i4);//false

整型缓存池

如果Integer的值是在[-128~127]之间,这些值会从Integer中的“整型缓存池”获取。
观察下面程序打印的结果

Integer i5 = 127; 
Integer i6 = 127;

System.out.println(i5 == i6); //true

上面程序不会在堆中新建对象,会直接从整型常量池中拿。在比较Integer的值是否相等时,一定要使用equals方法,这里用==比较是为了引出整型缓存池

在Integer的源码中可以看到有一个静态内部类IntegerCache,该类中维护了一个数组,整型缓存池的本质就是一个数组,该数组中默认的存储范围是[-128,127],也就是说当Integer的值在这个范围内的话,会从数组中获取,这就是为什么上面代码结果是true的原因了。另外我们可以通过参数来设置缓存池的上限。输入下面参数:

-XX:AutoBoxCacheMax=256

这样整型缓存池的上限就到了256,即在[-128,256]范围内的值会从数组中获取。

拆箱装箱和整型缓存

什么是自动拆箱和自动装箱?

  • 自动装箱:把基本类型转换为包装类类型

    Integer i1 = 10;

  • 自动拆箱:把包装类类型转换为基本类型

    Integer i1 = 10;
    int i2 = i1;
    

以上特性是jdk5中加入的,也就是说在jdk5版本之前是不支持自动装箱和自动拆箱的。

注意:在判断两个Integer类型是否相等时,要使用equals方法,不能使用”==”,Integer已经重写了Object中的equals方法。
这种写法

Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3==i4);//false

相当于

Integer i3 = new Integer(128);
Integer i4 = new Integer(128);

System.out.println(i3==i4);//false

整型缓存池

如果Integer的值是在[-128~127]之间,这些值会从Integer中的“整型缓存池”获取。
观察下面程序打印的结果

Integer i5 = 127; 
Integer i6 = 127;

System.out.println(i5 == i6); //true

上面程序不会在堆中新建对象,会直接从整型常量池中拿。在比较Integer的值是否相等时,一定要使用equals方法,这里用==比较是为了引出整型缓存池

在Integer的源码中可以看到有一个静态内部类IntegerCache,该类中维护了一个数组,数组中默认的存储范围是[-128,127],也就是说当Integer的值在这个范围内的话,会从数组中获取,这就是为什么上面代码结果是true的原因了。另外我们可以通过参数来设置缓存池的上限。输入下面参数:

-XX:AutoBoxCacheMax=256

这样整型缓存池的上限就到了256,即在[-128,256]范围内的值会从数组中获取。

日期类型

获取毫秒数

工作中基本上都会需要使用对时间的操作,java也提供了一些时间相关的类。
下面代码可以获取自 1970年1月1日 00时00分00秒 000毫秒 到当前的毫秒数。

package com.monkey1024.date;

/**
 * 获取自 1970年1月1日 00时00分00秒 000毫秒 到当前的毫秒数
 * 演示String和StringBuffer分别进行字符串拼接所需要的毫秒数
 */
public class DateTest01 {

    public static void main(String[] args) {

        long now = System.currentTimeMillis();
        System.out.println(now); 

        String s = "";
        StringBuffer sb = new StringBuffer(); 
        //获取拼接前的毫秒数
        long before = System.currentTimeMillis();
        for(int i=0; i<=100; i++){
            // s += i;拼接String
            // sb.append(i);拼接StringBuffer
        }
        //拼接后的毫秒数
        long after = System.currentTimeMillis();
        //总共耗时毫秒
        System.out.println(after - before);
    }

}

获取系统当前时间

在java.util包下面有个Date类,通过这个类可以获取系统的当前时间

package com.monkey1024.date;

import java.util.Date;

/**
 * 
 * 获取系统当前时间
 * 
 */
public class DateTest02 {

    public static void main(String[] args) {
        //获取系统当前时间    
        Date nowTime = new Date();
        System.out.println(nowTime); 

        Date d1 = new Date(0);//如果构造方法中参数传为0代表的是1970年1月1日
        System.out.println(d1);
    }

}

日期格式化类

上面代码中打印的日期格式不太符合中国的风格,国人一般习惯的时期格式是:
1970年01月01日 00时00分00秒

在java.text包下有个SimpleDateFormat类,通过这个类可以将日期修改为我们想要的风格

package com.monkey1024.date;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 
 * 日期格式化
 * 
 */
public class DateTest02 {

    public static void main(String[] args) {
        //获取系统当前时间    
        Date nowTime = new Date();
        System.out.println(nowTime); 

        Date d1 = new Date(0);//如果构造方法中参数传为0代表的是1970年1月1日
        System.out.println(d1);

        //1.创建日期格式化对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");
        //可以改成其他格式
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        //2.开始格式化(Date--->String)
        String strTime = sdf.format(nowTime);

        System.out.println(strTime); 
    }

}

上面代码中需要注意大小写区分
y表示年
M表示月
d表示日
H表示小时
m表示分钟
s表示秒
S表示毫秒

将String类型转换为Date类型

package com.monkey1024.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 
 * 将String类型转换为Date类型
 * 
 */
public class DateTest03 {

    public static void main(String[] args) {
        String strTime = "2017年01月01日 00:00:00 000";

        //将String日期转换成日期类型Date
        //String-->Date

        //1.创建日期格式化对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS"); //格式不能随意,应该和上面的字符串格式相同。

        //2.将字符串转换成日期类型
        Date d = new Date();
        try {
            d = sdf.parse(strTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        System.out.println(d); 
    }

}

Calendar简介

Calendar 类是一个抽象类,为操作日历方面提供了一些方法

package com.monkey1024.date;

import java.util.Calendar;

/**
 * 
 * Calendar
 * 
 */
public class DateTest04 {

    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();

        //查看当前日期是星期几
        int i = c.get(Calendar.DAY_OF_WEEK);
        System.out.println(i); //外国人将周日看做是第一天
         System.out.println(c.get(Calendar.DAY_OF_MONTH));

    }

}

关于@Deprecated的说明

通过源码可以看到,在java.util.Date类中的源码里面可以看到很多方法上面标有@Deprecated,这些方法是已经不建议使用了,对于开发者来说最好不要使用标有@Deprecated的方法了。

练习

1.编写代码获取2008年8月8日是星期几?
2.算一下你来到这个世界多少天?

答案

1.分析:首先获取2008年8月8日的Date类型,然后通过Calendar里面的DAY_OF_WEEK属性可以判断出示星期几

package com.monkey1024.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 
 * 编写代码获取2008年8月8日是星期几
 * 
 */
public class Exercise01 {

    public static void main(String[] args) {
         Calendar c = Calendar.getInstance();
         //获取2008-8-8的日历
         String strTime = "2008-08-08";
         Date d = new Date();
        try {
            d = new SimpleDateFormat("yyyy-MM-dd").parse(strTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }

         c.setTime(d);
         System.out.println(c.get(Calendar.DAY_OF_WEEK));
    }

}

2.分析:获取出生日期和当前日期的Date类型,然后将两个日期的毫秒值做减法,之后用这个毫秒值除以1000,再除以60,再除以60,再除以24得到天

package com.monkey1024.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 
 * 算一下你来到这个世界多少天
 * 
 */
public class DateTest04 {

    public static void main(String[] args) throws ParseException {
        //生日
        String birthday = "2016年06月15日";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        //将生日字符串转换成日期对象
        Date d1 = sdf.parse(birthday);
        Date d2 = new Date();
        //将两个日期的毫秒值做减法
        long time = d2.getTime() - d1.getTime();
        //除以1000,再除以60,再除以60,再除以24得到天
        System.out.println(time / 1000 / 60 / 60 / 24 );
    }

}

Math类简介

Math类概述

在java.lang包下,有个Math类,这个类包含用于执行基本数学运算的方法,如四舍五入,开方等等。

package com.monkey1024.math;

/**
 * Math类常用方法
 * 
 */
public class MathTest {

    public static void main(String[] args) {
        //圆周率
        System.out.println(Math.PI);
        //取绝对值
        System.out.println(Math.abs(-10));              

        //ceil天花板,会向上取值,结果是double
        System.out.println(Math.ceil(12.3));
        System.out.println(Math.ceil(12.99));

        System.out.println("-----------");
        //floor地板,会向下取整,结果是double
        System.out.println(Math.floor(12.3));            
        System.out.println(Math.floor(12.99));

        //获取两个值中的最大值
        System.out.println(Math.max(20, 30));

        //前面的数是底数,后面的数是指数,即2的3次方
        System.out.println(Math.pow(2, 3));

        //生成0.0到1.0之间的随机小数,包括0.0,不包括1.0
        System.out.println(Math.random());

        //四舍五入
        System.out.println(Math.round(12.3f));
        System.out.println(Math.round(12.9f));

        //开平方
        System.out.println(Math.sqrt(16));
    }

}

BigInteger类简介

BigInteger类概述

BigInteger类可以让超过Integer范围的数据进行运算,通常在对数字计算比较大的行业中应用的多一些。

package com.monkey1024.big;

import java.math.BigInteger;

/**
 * BigInteger可以让超过Integer范围的数据进行运算
 *
 */
public class BigIntegerTest01 {

    public static void main(String[] args) {

        BigInteger bi1 = new BigInteger("100");
        BigInteger bi2 = new BigInteger("2");

        System.out.println(bi1.add(bi2));                 //+
        System.out.println(bi1.subtract(bi2));            //-
        System.out.println(bi1.multiply(bi2));             //*
        System.out.println(bi1.divide(bi2));            ///(除)

        BigInteger[] arr = bi1.divideAndRemainder(bi2);    //取除数和余数

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

}

BigDecimal类简介

BigDecimal类概述

由于在运算的时候,float类型和double很容易丢失精度,在金融、银行等对数值精度要求非常高的领域里面,就不能使用float或double了,为了能精确的表示、计算浮点数,Java提供了BigDecimal。
注意:如果对计算的数据要求高精度时,必须使用BigDecimal类

package com.monkey1024.big;

import java.math.BigDecimal;

/**
 * BigDecimal简介
 *
 */
public class BigDecimalTest01 {

    public static void main(String[] args) {
        System.out.println(2.0 - 1.1);
        
        //这种方式在开发中不推荐,因为不够精确
        BigDecimal bd1 = new BigDecimal(2.0);		
        BigDecimal bd2 = new BigDecimal(1.1);
        System.out.println(bd1.subtract(bd2));
        
        //开发时推荐通过传入字符串的方式
        BigDecimal bd3 = new BigDecimal("2.0");		
        BigDecimal bd4 = new BigDecimal("1.1");
        System.out.println(bd3.subtract(bd4));
        
        //这种方式在开发中也是推荐的
        BigDecimal bd5 = BigDecimal.valueOf(2.0);	
        BigDecimal bd6 = BigDecimal.valueOf(1.1);
        System.out.println(bd5.subtract(bd6));
        //计算除法的时候需要设置保留小数的个数
        BigDecimal bd3 = new BigDecimal("10");
        BigDecimal bd4 = new BigDecimal("3");
        //四舍五入保留两位小数
        BigDecimal result = bd3.divide(bd4,2,BigDecimal.ROUND_HALF_UP);
        //上面方法在jdk9中被废弃了,推荐使用下面方法
        BigDecimal result = bd3.divide(bd4,2, RoundingMode.HALF_UP);
    }

}

DecimalFormat类

DecimalFormat类概述

在一些金融或者银行的业务里面,会出现这样千分位格式的数字,¥123,456.00,表示人民币壹拾贰万叁仟肆佰伍拾陆元整,java.text包下提供了一个DecimalFormat的类可以满足这样的需求。

package com.monkey1024.big;

import java.text.DecimalFormat;

/**
 * DecimalFormat简介
 *
 */
public class DecimalFormatTest01 {

    public static void main(String[] args) {

        //格式化人民币
        String money = DecimalFormat.getCurrencyInstance().format(123456);
        System.out.println(money);

        //创建数字格式化对象
        //需求:加入千分位.
        DecimalFormat df = new DecimalFormat("###,###");

        //开始格式化
        System.out.println(df.format(1234567)); //"1,234,567"


        //加入千分位,保留2位小数
        DecimalFormat df1 = new DecimalFormat("###,###.##");

        System.out.println(df1.format(1234567.123)); //"1,234,567.12"


        //加入千分位,保留4位小数,并且不够补0
        DecimalFormat df2 = new DecimalFormat("###,###.0000");
        System.out.println(df2.format(1234567.123)); 


    }

}

enum简介

enum简介

在日常开发中可能有一些数值是固定的,比如一年只有4个季节,春夏秋冬。我们可以自己定义一个类里面存放这4个季节。在jdk5之后,引入了枚举(enum)的概念,可以通过enum去定义这四个季节。enum本质还是一个类,枚举类型的父类:java.lang.enum。

定义常量类,里面存放四季

package com.monkey1024.enumtest;

/**
 * 常量类
 *
 */
public class Constant {
    
    public static final String SPRING = "spring";
    
    public static final String SUMMER = "summer";
    
    public static final String AUTUMN = "autumn";
    
    public static final String WINTER = "winter";
}

定义枚举类存放四季

//使用枚举存放四季
public enum Season{
    Spring,Summer,Autumn,Winter
}

使用枚举

//调用枚举
System.out.println(Season.Summer);

//调用常量
System.out.println(Constant.SUMMER);

我们可以在枚举中添加属性,提供对应的构造方法进行赋值

package com.monkey1024.fnumber;

//使用枚举存放四季
public enum Season {
    Spring(1,"春天"),Summer(2,"夏天"),Autumn(3,"秋天"),Winter(4,"冬天");

    //添加属性
    private int id;
    private String name;
    
    //构造方法
    Season(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

获取枚举中的属性

System.out.println(Season.Summer.getName());

伪随机数

Random类概述

Random类在java.util包下,使用这个类可以生成随机数

package com.monkey1024.random;

import java.util.Random;

public class RandomTest01 {

    public static void main(String[] args) {
        
        Random r = new Random();
        //生成int类型的随机数
        int ran = r.nextInt(101); //[0-100]之间的随机数
        System.out.println(ran);
        
        //循环生成5个随机数
        for(int i=0;i<5;i++){
            System.out.println(r.nextInt(101));
        }
                
    }

}

SecureRandom简介

Random生成的随机数是可预测的,属于弱随机数,对于随机数敏感的场景,比如抽大奖,需要使用SecureRandom来生成随机数,该类生成的随机数是强随机数,强随机数生成的结果取决于内存状态,硬盘空闲空间,进程数量等等。

下面示例演示了使用相同的种子,弱随机数和强随机数生成的结果:

//弱随机数
Random r1 = new Random(1);
Random r2 = new Random(1);

//循环10次,打印结果一致
for (int i = 0; i < 10; i++) {
    System.out.println(r1.nextInt(100));
    System.out.println(r2.nextInt(100));
}


//强随机数
byte[] bytes = new byte[3];
SecureRandom sr1 = new SecureRandom(bytes);
SecureRandom sr2 = new SecureRandom(bytes);

//打印结果不一致
for (int i = 0; i < 10; i++) {
    System.out.println(sr1.nextInt(100));
    System.out.println(sr2.nextInt(100));
}

练习

完成一个彩票机选号码生成器,这里以双色球为例,双色球每注中奖号码由6个不同的红色球号码和1个蓝色球号码组成。红色球号码从133中选择;蓝色球号码从116中选择。

答案

分析:随机的从133中选择6个不同的数字,需要去重,随机从116中选择1个数字,可以组成一注中奖号码。

import java.util.Arrays;
import java.util.Random;

/*
    完成一个彩票机选号码生成器,这里以双色球为例,
    双色球每注中奖号码由6个不同的红色球号码和1个蓝色球号码组成。
    红色球号码从1~33中选择;蓝色球号码从1~16中选择。
 */
public class ColorBall {
    public static void main(String[] args) {
        //初始化双色球号码
        int[] balls = new int[33];

        for (int i = 0; i < balls.length ; i++) {
            balls[i] = i + 1;
        }

        //定义数组保存6个红球号码
        int[] result = new int[6];
        //定义下标的变量
        int index = 0;

        Random r = new Random();

        //创建数组标记红球是否重复
        boolean[] isUsed = new boolean[balls.length];

        while (true) {
            //生成随机数作为数组下标
            int red = r.nextInt(33);

            //判断该随机数是否生成过
            if (isUsed[red]){
                continue;
            }

            //将当前随机数标记为使用过
            isUsed[red] = true;

            //根据下标获取一个红球号码,放入到result数组中
            result[index++] = balls[red];

            //判断是否生成了6个红球
            if (index == 6) {
                break;
            }

        }


        //排序
        Arrays.sort(result);
        System.out.println("红球:" + Arrays.toString(result));

        //生成篮球
        int blue = r.nextInt(16);
        System.out.println("蓝球:" + balls[blue]);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值