常用类(1)

Java基础精讲
本文深入讲解Java中的Integer类、String类、StringBuffer类等核心概念,包括包装类的使用、自动装箱拆箱、字符串操作及性能优化技巧,适合Java初学者和进阶者阅读。

一.使用包装类

Integer类继承了Number父类和Comparable父接口(所以自身具有比较方法compareTo())。Integer类里面唯一的一个属性(private final int value),8中基本包装类,每一种对象里面都包含了一个对应的value值,Byte里面包含一个byte的,Boolean的里面包含一个boolean的,如下所示:

源码:public final class Integer extends Number implements Comparable {} 说明:继承了Number和内部比较器
源码: Integer属性有个value: private final int value;
源码: Boolean属性也有个value: private final boolean value;

从这里我们可以得到包装类的特点:
Integer类的唯一的一个实例成员:private final int value;
该类的对象一旦创建就不能被修改。对象不可改变的特点。
包装类的优缺点
优点:安全。多个线程同时访问一个对象,因为不能修改,是只读的,所以是安全的。
缺点:当你需要使用不同value值的Integer对象的时候,需要创建多个Integer对象(比如需要10个Integer对象就必须得new10次)。对象不能复用(我修改你的值再去用)。造成内存的浪费。
4.包装类继承体系图

5.Integer类的基本使用
Integer类的一些常用方法,如下表所示:

intcompareTo(Integer anotherInteger) 在数字上比较两个 Integer 对象。
static Integerdecode(String nm) 将 String 解码为 Integer。
booleanequals(Object obj) 比较此对象与指定对象
inthashCode() 返回此 Integer 的哈希码。
intintValue() 以 int 类型返回该 Integer 的值。
static intparseInt(String s) 将字符串参数作为有符号的十进制整数进行解析。
StringtoString() 返回一个表示该 Integer 值的 String 对象

二、自动装箱和拆箱
在jdk1.5之后针对8种包装类,推出了一种新的创建对象的语法。
自动装箱autoboxing:将一个基本数据类型的数据,直接赋值给对应包装类对象的过程;底层通过调用integer.valueOf()实现的
自动拆箱autounbxing:将一个包装类对象直接赋值给一个对应的基本数据类型的过程,底层通过intValue()实现。

import java.util.Arrays;

/**
 *Integer类的基本使用
 */
public class TestInteger{
    public static void main(String[] args) {
        //test();
        test3();
    }
    public static void test(){
        //创建Integer对象
        Integer integer=new Integer(10);
        integer=new Integer("123");
        //可以使用Integer里面的静态工厂方法创建对象
        integer=Integer.valueOf(234);
        integer=Integer.valueOf("ff",16);//255,用16进制解析这个字符串,返回它对应的整数值作为包装类对象。
        System.out.println(integer);//调用的是它的toString方法,Integer重写了这个方法

        /*
            Integer里面byteValue的源码(其实这里面就是强制类型转换)
           public byte byteValue() {
        return (byte)value;
    }
         */
        System.out.println(integer.byteValue());//将255强制转换为byte类型,返回-1(超过了byte的表示范围,所以返回的值为-1)
        /*
          intValue()方法的源码,其实相当于get方法
         public int intValue() {
             return value;
         }
         */
        System.out.println(integer);//255
        System.out.println(integer.intValue());//255
        System.out.println(integer.compareTo(new Integer("123")));//返回1
        //parseInt()是静态方法,所以用类名访问
        System.out.println(Integer.parseInt("123"+1));//124
        //用二进制解析这个字符串,
        System.out.println(Integer.parseInt("1111",2)+1);//16
    }

    //此方法用于测试自动装箱和拆箱
    private static void test1(){
        Integer integer=1;//可以把一个基本数据类型的值或者变量,直接赋值给给它对应的包装类对象
        int age=10;//将一个对象(里面的值)直接赋值给了一个变量
        /*这句代码只是语法上是这样的,编译之后就变样了。自动装箱和自动拆箱只是对于程序员来说简单的语法而已,编译之后class文件中的内容是:
        integer=integer.valueOf(age)
         */
        Integer integer1=age;//也可以把一个基本数据类型的变量,直接赋值给它所对应的包装类对象。
        Boolean bool=true;

        //自动拆箱(jdk1.5之前去对象里取一个数值需要调用inValue()方法来实现同样的功能)
        age=integer;//直接将一个对象(里面装的值)赋值给对应的基本数据类型的变量
        /*
        自动拆箱在class文件中的内容:
        age=integer.intValue();
        */
    }

    //定义Integer数组,长度为5,然后静态初始化
    //使用自动装箱随机初始化,然后打印数组内容
    //然后使用Arrays排序,然后打印
    static void test2(){
        Integer[] integers={
            getRandomNumber(10,50),
            getRandomNumber(10,50),
            getRandomNumber(10,50),
            getRandomNumber(10,50),
            getRandomNumber(10,50)
        };
        System.out.println(Arrays.toString(integers));
        Arrays.sort(integers);//Arrays.sort()的这个sort()方法在底层也是通过comparable来进行比较的
        //Integer已经实现了内部比较器
        /*Integer 实现了内部比较器功能
          public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
         */
        System.out.println(Arrays.toString(integers));
    }

    //定义一个生成一个随机数方法
    public static int getRandomNumber(int min,int max){
        return (int)(Math.random()*(max-min)+min);
    }

    //一道面试题
    public static void test3(){
        //只要使用了new一定是个新对象
        Integer integer0=new Integer(10);
        Integer integer1=new Integer(10);
        System.out.println(integer0 == integer1);//false  这两个是new出来的,很显然是两个不同的对象,所以结果是false

        //这里是同一个对象,这就是使用静态工厂方法带来的优点,静态工厂方法虽然也创建对象了,但是在底层实现的时候不一定调用的new
        /*valueOf的底层实现,如果这个i大于.low(-128)或者小于.high(127),返回
        public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
        }
        ---------------------------------------------------------------------------------------------------------------
         返回来的static final Integer cache[];使用static final 修饰的,
         
         Integer对象有一个缺点,一旦创建就不能改变,
         如果我们需要不同的Integer对象,需要不停的new。。。这时候会造成内存的浪费,因此JDK针对这个特点提供了什么机制呢?
         它在Integer 类加载的时候,提前创建好了256个Integer对象[-128,127],放在了cache[] 这个数组里面了。这叫对象池,
         提前创建好一堆对象,当用的时候,直接在里面拿就可以了。
         要注意在类加载的时候就创建好了,那么怎么使用呢,如果我们用valueOf创建的对象再它这个范围内,则用它已经创建好的。
         如果不在这个区间,则用new Integer(i);创建一个新的对象。
         那么用什么得到这256个对象呢?用valueOf()得到
         */
        Integer integer2=Integer.valueOf(10);
        Integer integer3=Integer.valueOf(10);
        System.out.println(integer2 == integer3);//true

        Integer integer4=Integer.valueOf(128);
        Integer integer5=Integer.valueOf(128);
        System.out.println(integer4 == integer5);//false
    }
}

第三节Java.lang.String

1.前言:

String 类是用来描述字符串对象的,任何一个字符串常量都是该类的一个实例。”123” 是一个String对象。

2.特点

1:实现了内部比较器接口java.lang.Comparable 可以进行内部比较。compareTo()

源码: public final class String implements java.io.Serializable, Comparable, CharSequence { } 说明:String类继承了后面那3个接口

2:final 修饰该类,不能有子类。
3:String类底层使用char[] 实现对字符序列的存储。

3.常用方法练习

String构造方法 public String(char value[]) }
String构造方法 public String(String original)
String构造方法 public String(char value[], int offset, int count)
剩下的常用方法,见下面代码
import java.util.Arrays;

/**
 *String方法练习
 */
public class TestString {
    public static void main(String[] args) {
        test0();
    }

    //String方法练习
    public static void test0() {
        byte[] bs = {65, 66, 67, 68};
        String str = new String(bs);   //将一个字节数组生成了一个字符串对象
        System.out.println(str);//  打印结果为ABCD,所以这里的65是对应的ASIIC码里面的值

        String str1 = new String("123456789");
        System.out.println(str1);

        System.out.println(str1.charAt(3));//返回String对象里面指定索引位置的字符,是个char类型
        System.out.println("bc".compareTo("be"));//返回-2。
        System.out.println("bc".concat("de"));//字符串的连接,返回bcde
        System.out.println(str1.contains("34"));//str这个对象里面是否包含了子串"34"  //true
        System.out.println(str1.endsWith("789"));//这个字符串是不是以什么什么结尾。//true
        System.out.println(str1.startsWith("123"));//这个字符串是不是以什么什么开头。//true
        //这里又new出来一个新的对象,因为String重写了equals()方法,所以这里是根据内容比较。内容相同返回true
        System.out.println(str1.equals(new String("123456789"))); //true
        //下面的这个方法是一个静态方法。(了解)
        // 前面有三个特殊符号,则后面就要传进来3个参数。不同的符号接收不同的变参的内容,最后返回格式化后的结果
        System.out.println(String.format("%s攻击了%s,受到了%d点伤害", "阿基里斯","赫克托", 100));

        //这里讲一个字符串还原成一个【字节数组】
        //我们想一下"123456789"对应的字节数组是啥样的?1对应的是49,2对应50,51,52,..............
        //打印的结果[49,50,51,52,53,54,55,56,57]
        System.out.println(Arrays.toString(str1.getBytes()));//str1.getBytes()这是一个字节数组

        System.out.println(str1.indexOf('1'));//在这个字符串里面第一个出现'1'这个字符的索引的位置  //结果0
        System.out.println(str1.indexOf("54"));//也可以是字符串,这个字符串不存在,返回-1;

        System.out.println(str1.isEmpty());//返回false

        System.out.println(str1.lastIndexOf("23"));//从后向前找,但是索引还是从前向后数。//返回1
        System.out.println(str1.length());//字符串的长度9
        System.out.println(str1.replace("4","68"));//返回新的字符串对象1236856789

        ////以下划线分割符,返回切割后的数组//[java, c, c#, php]
        System.out.println(Arrays.toString("java_c_c#_php".split("_")));

        //注意到这里这个str1还是"123456789"

        //求子串的,从7到末尾
        System.out.println(str1.substring(7));// 结果为:89
        System.out.println(str1.substring(3,6));//返回子串,包含3,不包含6  //结果:456
        System.out.println("abc".toUpperCase());//转为大写  //结果为ABC
        System.out.println("ABC".toLowerCase());//转为小写   //结果为abc
        //对这个字符串前导空白字符和后延空白字符去掉,注意中间的去不掉
        System.out.println("     a b c    ".trim());//输出结果a b c

        //剩下的valueOf(),是重载,是静态的方法,将8种基本数据类型的数据转换为字符串的方法,返回的是String
        //返回的是1的字符串对象,这个是有int转换为String,那么是怎么转换的呢?依赖于Integer里面的int到String
        /*源码:
             public static String valueOf(int i) {
                return Integer.toString(i);
            }
         */
        System.out.println(String.valueOf(1));
        //也可以将一个对象转换为字符串
        //将对象转换为字符串都依赖于对象的toString方法,也就是底层依赖的是对象的toString()方法。
        //由于这个对象的toString(),我们没有重写,所以用过的是父类的toString方法
        /*
         public static String valueOf(Object obj) {        //这里存在多态,父类引用指向子类对象
            return (obj == null) ? "null" : obj.toString();
        }
         */
        System.out.println(String.valueOf(new TestString())); //结果为:com.sxt.first.TestString@5cad8086

    }

    //练习1:实现方法:对应任意的字符串,判断字符串中是否包含了数字。
    public boolean hasNumber(String str){
        if(str==null) return false; //判断特殊情况
        final int LEN=str.length();
        if(LEN==0) return false;    //判断特殊情况
        for (int i = 0; i < LEN; i++) {
            char ch=str.charAt(i);
            if(ch>='0' && ch<= '9'){  //或者这里将'0'改为48,'9'改为57也可以但是可读性不好
                return true;
            }
        }
        return false;
    }

    //练习2:实现方法:统计任意的的字符串中,包含指定字符的个数。
    public int test4(String str,char ch){
        if(str==null) return 0; //特殊情况处理
        final int LEN=str.length();
        if(LEN==0) return 0;   //特殊情况处理
        int count=0;//定义一个计数器
        for (int i = 0; i < LEN; i++) {
            if(ch==str.charAt(i)){
                count++;
            }
        }
        return count;
    }
}

字符串"123456789"在对象里面是以什么形式存储的呢?也就是说字符串在底层使用什么来实现具体字符的保存方式的?

看源码:/** The value is used for character storage. */ private final char value[];

也就是说String类的底层实现是使用char[] 数组来保存这些字符的。而且是私有的,用final修饰的。用final修饰的意味着什么?我们以前说过,final修饰的引用数据类型意味着不能再指向其他对象,在这里也就是说这个value不能指向其他数组了。数组的特点是长度固定。那么我们一旦确定了数组,则长度不能变。那么**数组内容可不可以变呢?**通过下面的代码证明,可以

//测试用final修饰的数组的内容可不可以改变?
public class Test{
    public static void main(String[] args) {
        final char value[]={'1','2'};
        //value=new char[10];//这行报错,value不能再指向另外一个数组了。
        //那么里面的内容能不能改变呢?
        value[0]='a';
        System.out.println(Arrays.toString(value)); //结果为[a,2].结论是可以修改字符的内容的。
    }
}

但是这个类是private 的,并且没有提供set方法,也就是对外没有提供修改value的方法,综上可知:

**Final 修饰value,所以final不能指向其他的数组,那么数组一旦长度确定了,就不能修改了,然后String类又没有提供让我们修改元素的方法,不能通过方法修改value 的值。所以得出一个String对象最大的特点:对象一旦创建就不能修改了。
**

优点:线程安全。
缺点:在修改字符串对象的过程中,会产生很多字符串新的字符串对象,造成内存的浪费。

//验证String对象一旦创建,就不能改变(我们在上面的代码中对“123456789”这个字符串进行方法,其实都是生成了一个新的字符串,如果我们打印str1,那么它的结果还是123456789)
public class TestString {
    public static void main(String[] args) {
        String str="1234";
        str.concat("456");//字符串的连接,这也是产生了一个新的字符串,只是没有任何的引用指向它。
        System.out.println(str.replace("4","68"));//12368
        System.out.println(str);//1234
    }
}

通过练习得出一个结论,所有的看似对String对象修改的方法,其实本质上都没有修改源字符串,都是生成了一个新的字符串对象。这也会造成一个很大的缺点,会产生很多的字符串对象,造成内存的浪费。(这一点有点像Integer)一定要注意这个不能变是由两个原因导致的,一、由final修饰;二、对外没有提供修改的方法。

//疑问:是不是str被改变了??不是。str第一次指向“123” 第二次指向“345”,怎么验证呢?看下一段代码。
public class TestIntern{
    public static void main(String[] args) {
        String str="123";
        str="345";
        System.out.println(str);
}
public class TestIntern{
    public static void main(String[] args) {
        String str="123";
        String s=str;//此时str和s都指向了“123”
        //如果String对象不能改变,则s指向123,str指向456
        //如果String对象可以改变,那么s和str都指向456
        str="456";//这里str重新指向了“456”
        System.out.println(s);//123  如果可以改变,则意味着s和str的结果都是456
        System.out.println(str);//456
}

4.Java针对String 类的特殊的处理、针对缺点的弥补

String 对象的赋值方式就很特殊。String s = “123”;
我们说String对象由很多对象创建只用了一次就不用了,造成内存的浪费,可以想一下,对于不可变的对象,在Integer那里是怎么做的?是尽量复用相同的对象,给你创建好了,用就行了。那么String类的扣留机制就是尽量复用已经创建好的,内容相同的字符串对象。那么怎么复用?如何复用呢?把下面的代码理解了就可以了。看一下哪一种写法是让它尽量的复用我们已经存在的字符串对象,那么使用这种方式就可以了。双等号(==)是检测地址的,地址相同就代表着复用。

/**
 *String类的扣留机制
 * 尽量复用已经创建好的,内容相同的字符串对象。
 */
public class TestStringIntern{
    public static void main(String[] args) {
        String str="123";
        String s=str;
        str="345";
        System.out.println(s);
        System.out.println(str);
        String s1="a";
        String s2="b";
        //s3直接指向方法区常量池中的"ab",s3存储的是"ab"在常量池中的地址。
        //这种写法会创建0-1个对象。如果常量池中没有就添加一个,如果已经存在就直接指向。
        String s3="ab";//这种赋值语句可以创建0-1个对象,如果常量池中有,就直接指向,如果没有,则把“ab”对象放在常量池中,它指向这个对象。
        //编译器在编译期对下述的代码做了优化,将两个常量合并为"ab"
        //因为"ab"已经存在于常量池中,所以s4也直接指向常量池中的"ab"
        String s4="a"+"b";//这条语句没有创建对象,它直接指向常量池中的"ab"
        //s5指向的是堆内存,堆内存中的对象地址
        String s5=s1+s2;
        //s6指向堆内存
        String s6=new String("ab");  //这句代码下面有内存分析图
        //这种情况会创建1-2个对象,堆内存中一定是创建了一个对象,
        //如果常量池中没有abc,那么常量池中会添加一个abc;如果已经存在了,就不添加。
        String s9="abc";
        //如果常量池中包含了"ab",那么就直接返回常量池中的地址,
        // 如果不包含"ab",那么就在常量池中添加"ab"。并返回常量池地址。//所以intern()方法一定是返回常量池地址的。
        //该方法允许在运行区将字符串动态的添加到常量池。
        String s7=new String(s1+s2).intern();
        String s8="ab";

        System.out.println(s3==s4);//true
        System.out.println(s3==s5);//false
        System.out.println(s3==s6);//false
        System.out.println(s3==s7);//true
        System.out.println(s3==s8);//true

    }
}

那么s3、s4、s7、s8这样的写法都实现了字符串对象内容相同的复用,那么s5、s6这种写法就不建议使用了。这里我们解释一下为什么? 在运行期jvm给每一个java 的应用程序在方法区开辟了一块内存,用来存方法字符串常量,字符串常量池 string constant pool,该常量池由String类自己维护。所有的出现在程序中的字符串常量 “”(即用双引号扩起来的) 都会在编译期 就确定下来,到了运行期都会添加到常量池。常量池中的字符串对象的内容必须是唯一的。不能存在两个字符串对象具有相同的内容。
通过上面的代码,我们得出一个结论:以后创建字符串对象的时候,尽量使用String s = “123”;这种方式(因为创建的对象少),除非有特殊的要求才使用new 去创建。
说明:什么叫字符串常量呢?出现在程序中 的所用用双引号括起来的都叫字符串常量,例如上面代码中的"a",“b”,“ab” 而s1、s2是变量。

第四节StringBuffer、StringBuilder

1.特点:底层使用char[] value 实现。通过方法调用可修改它的长度和内容。该类提供了大量的修改value 内容的方法。(我们学StringBuffer主要就是学习这些方法)
2.StringBuilder 是在jdk1.5出现的。提供了和StringBuffer一致的API。该类的出现是为了在线程安全的情况下实现对StringBuffer的一个替代,来实现更高的效率。StringBuffer是线程安全的类,效率相对较低。StringBuilder是线程非安全的,效率更高。
在底层也是使用char value[] 数组来存的,char[]数组是继承父类里面的。先看一下源码:

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{}
/*The value is used for character storage/ char[] value;
/**The count is the number of characters used.*/ int count; 指的是元素的个数

说明:这里的char[] value 没有用final修饰,那么这个value 就可以指向其他长度的char[] 数组了(可以理解成数组长度可变了)。并且提供了set、 get方法(也就是大量的提供了修改元素的方法)

/**
 *StringBuffer的一些常用方法
 */
public class TestStringBuffer {
    public static void main(String[] args) {
        test1();
    }
    public static void test1(){
        //对象刚刚创建,这个char数组就创建了,里面的只是默认值null
        StringBuffer sb=new StringBuffer();
        //在这里我们测一下刚刚创建出来的数组的长度是多少?
        System.out.println(sb.capacity());//输出它的容积16
        //length()是求它的有效的字符个数
        System.out.println(sb.length());//输出字符个数0

        //尾部添加
        sb.append(1);//这个1在底层先转换为字符串(依赖于toString())再添加进去
        //我们这个sb里面存的是字符序列,你里面添加对象的时候都要转化为字符串对象,那么怎么转呢?
        // 调用toString(),我们没有重写,就用默认的
        sb.append(new TestStringBuffer());//在这里调用了new TestStringBuffer()对象的toString()方法
        //插入
        sb.insert(1,true);//第一个参数是偏移量,第二个参数是想要插入的值
        //delete删除
        int index=sb.indexOf("@");//求出@的索引
        sb.deleteCharAt(index);//括号里面是索引值
        index=sb.indexOf(".");
        sb.delete(index,sb.length());//删除一个区间,前闭后开的
        //修改
        sb.setCharAt(5,'_');//第一个参数:修改位置的索引;第二个参数:要修改的值。
        //sb.setLength(6);//设置序列长度,超过的内容直接被截掉
        System.out.println(sb.length());//8
        System.out.println(sb.capacity());//82  当我们往里面插入内容的时候,当容量不够的时候,会进行扩容
        
        //让长度和容量一致 //这个方法就是将空白的没有包含有效字符的删掉
        sb.trimToSize();//trim是剪裁的意思,例如:当容量是82,有效数据是8时,会造成容量的浪费,这个时候为了让容量个数据长   度保持一致。

        System.out.println(sb.length());//有效数据8个
        System.out.println(sb.capacity());//容量是8  
        System.out.println(sb);//以上的操作都是从原字符串的基础上改的。
    }
}

第五节 其他的常用类

1.java.lang.Runtime

Java运行时类,这个类在一个java程序中只有唯一的一个实例,而且该实例是由jvm创建的。如何得到它唯一的实例呢?是我们的应用程序和jvm之间的一个桥梁,通过该桥梁可以访问某些jvm的功能和属性。

import java.io.IOException;

/**
 * 测试Runtime的一些用法
 */
public class TestRuntime {
    public static void main(String[] args) throws IOException {
        //得到实例的唯一方式
        Runtime runtime=Runtime.getRuntime();
        //访问JVM的某些功能
        //返回JVM的可用内存和总内存
        long l=runtime.freeMemory();
        l=runtime.totalMemory();
        //调用垃圾回收
        runtime.gc();
        //结束虚拟机
        //runtime.exit(0);
        //可以使用JVM去执行本地的程序
        Process process=runtime.exec("notepad.exe E:\\ideaprojects\\javase\\oop1018\\src\\com\\sxt\\first\\TestRuntime.java");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //销毁程序
        process.destroy();
    }
}

2.Java.lang.System 系统工具类 都是静态方法

out:是System 类的静态成员变量。代表了我们标准的输出设备,控制台。该对象是在系统启动的时候进行初始化的。
in:是System 类的静态成员变量。代表了我们标准的输入设备,键盘。该对象是在系统启动的时候进行初始化的。

/**
 * 测试System的一些用法
 */
public class TestSystem {
    public static void main(String[] args) {
        int[] arr={11,3,4,5,6,7};
        int[] array=new int[3];
        System.arraycopy(arr,1,array,0,3);
        System.out.println(Arrays.toString(array));

        //
        long time=System.currentTimeMillis();
        test();
        long cost=System.currentTimeMillis()-time;
        System.out.println(cost);
    }
    //此方法用于测试算法的优劣
    static void test(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

3.java.lang.Math 数学工具类

/**
 * 测试Math的一些方法方法
 */
public class TestMath {
    public static void main(String[] args) {
        System.out.println(Math.random());//[0.0-1.0)
        System.out.println(Math.abs(-1));//输出1,此方法用于求绝对值
        System.out.println(Math.PI);
        System.out.println(Math.floor(1.1));//输出1.0,此方法用于向下取整
        System.out.println(Math.ceil(1.1));//输出2.0,此方法用于向上取整
        System.out.println(Math.round(4.4));//输出4
        System.out.println(Math.round(4.5));//输出5
        System.out.println(Math.sqrt(9));//输出3.0
        System.out.println(Math.pow(3,4));//输出81,此方法表示几的几次幂
        //弧度转为角度
        System.out.println(Math.toDegrees(1));//57.29577
        //角度转为弧度
        System.out.println(Math.toRadians(180));//3.1415926
    }
}

4.java.util.Random

这是一个专门用于求各种随机数的工具类。

import java.util.Random;

/**
 * 测试Random类的一些方法
 */
public class TestRandom {
    public static void main(String[] args) {
        Random random=new Random();
        //随机的int值(有可能是正值也有可能是赋值)
        int i=random.nextInt();
        //将随机得到的负数变为整数,一种方法是取绝对值,还有一种方法如下所示:
        i >>>=1;//等价于i=i>>>1
        int min=10;
        int max=12;
        //生成一个[min,max)之间的随机数
        i=(random.nextInt()>>>1)%(max-min)+min;
        System.out.println(i);

        i=random.nextInt(10);//生成一个随机数[0,10)
        System.out.println(i);
        random.nextLong();
        random.nextFloat();
        random.nextDouble();
        System.out.println(random.nextBoolean());
    }
}

今日练习:
1:自定义方法:实现获得一个随机字符的功能(要求,随机字符必须是26个英文字符,大小写也随机)。
2:使用上面定义的方法,去获得20个随机字符,添加到一个StringBuffer对象中。并打印内容。然后实现将对象中的小写字符删除,并打印剩余的大写字符。
3.实现算法,对于任意给定的字符串,对该字符串求出统计的结果:只对字符有效

**
 * 常用类练习
 */

public class Test1{
    public static void main(String[] args) {
        printUpperCase();
        count("abcfagf");
    }
    //1:自定义方法:实现获得一个随机字符的功能(要求,随机字符必须是26个英文字符,大小写也随机)。
    public static char randomChar(){
        int num1=MyUtil.getRandomNumber(0,2);
        int num2=MyUtil.getRandomNumber(65,91);
        if(num1==0){
            return (char)num2;
        }else{
           return (char)(num2+32);
        }
    }
    //2:使用上面定义的方法,去获得20个随机字符,添加到一个StringBuffer对象中。并打印内容。
    // 然后实现将对象中的小写字符删除,并打印剩余的大写字符。
    public static void printUpperCase(){
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<20;i++){
            sb.append(randomChar());
        }
        System.out.println(sb);
        //调用定义的delete方法
        delete(sb);
        System.out.println(sb);
    }
    //实现将对象中的小写字符删除,并打印剩余的大写字符。
    public static void delete(StringBuffer str){
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)>=97 && str.charAt(i)<=122){
                str.deleteCharAt(i);
                delete(str);
            }
        }
        //System.out.println(str);

    }
    //实现算法,对于任意给定的字符串,对该字符串求出统计的结果:只对字符有效。
    public static void count(String str){
        StringBuffer sb=new StringBuffer(str);
        int count=1;
        char str1=sb.charAt(0);
        for (int i = 1; i < str.length(); i++) {
            if(str1==str.charAt(i)){
                count++;
                sb.deleteCharAt(i);
            }
        }
        System.out.println(str1+"-"+count);
        sb.deleteCharAt(0);
        //System.out.println(sb);
        if((sb.toString().length())>=1){
            count(sb.toString());
        }

    }
}
//生成随机数的工具类
class MyUtil{
    private MyUtil(){}
    public static int getRandomNumber(int min,int max){
        return (int)(Math.random()*(max-min)+min);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值