【JavaSE基础】04-常用类API(二)

《JavaSE系列教程》 本专栏内容是为零基础正在学习Java的学习者量身定制的学习路线及方案,本教程字数超20w+,插图超过400+,知识体系极其全面,案例极其丰富。本配备有专门的学习群及学习视频,读者可加学习群与正在学习该阶段的人一同学习,有任何不懂的也可以观看于此教程配套的学习视频。 阅读详情

1、包装类(Wrapper Clas)

(0)、包装类的引入及其描述

先来看一下以下两个主要的需求:

  • 1、输出100的二进制、八进制、十六进制表示
  • 2、判断一个数据是否在 int 范围内

在还没有学习到常用类,没有体会到API提供的强大功能之前,我们可能会首先想到,我该怎么去实现这个需求呢?但是,现在是时候换一个想法了:API提供什么可以直接拿来用的方法了呢?从此刻起,做一名拿来主义。能拿来的绝不自己创造,“ 不要重复创造轮子 ”,并且我们也不会比哪些开发Java 的人写出的方法更优,当然为Java写类库,很酷!

在拿来之前,回想一下,之前来说,我们能够随手拿来的好像都只是引用数据类型的对象,它们在自身类中定义了一些成员方法,创建对象之后就可以去调用,但是基本数据类型(原始数据类型),如何实现呢?

为了对基本数据类型进行更多、更方便的操作,Java为四类八种基本数据类型提供了对应的类类型,亦即包装类(Wrapper Class)。
在这里插入图片描述

最常用的操作:基本类型和字符串的转换。

(1)、Number 抽象类

0:java.lang包下的Number是一个抽象类,在使用的时候,使用的是具体的子类得对象,描述说:抽象类 Number 是 BigDecimal、BigInteger、Byte、Double、Float、Integer、Long 和 Short 类的超类。 Number 的子类必须提供将表示的数值转换为 byte、double、float、int、long 和 short 的方法。

A:成员变量:【Field Summary】没有

B:构造方法:【Constructor Summary】仅有一个无参构造,public Number() { } 抽象类的无参构造仅仅是为了工子类(具体类)初始化使用,不可以创建对象。

C:成员方法:【Method Summary】

  • a、已实现,供子类继承

    • (1)public byte byteValue()

    • (2)public short shortByte

    • 基础语法阶段说明过,byte、short在参与运算的时候会自动提升为int类型,如果想要得到byte、short结果的话,就需要对int类型进行强制类型的转换。已经实现两个方法底层的源码就是将 intValue 方法的返回值进行了一个强制类型的转换。

  • b、尚未实现,供子类重写实现

    • (1)public abstract int intValue()

    • (2)public abstract long longValue()

    • (3)public abstract float floatValue()

    • (4)public abstract double doubleValue()

    • 面向对象抽象类讲解的时候,我们建议大家永远手动给出抽象成员方法的默认修饰符public abstract (无论是接口或是抽象类的抽象方法),这就是原因。Java大师们都给了,你凭什么不给。

(2)、Integer 类 *

0:java.lang包下的Integer类,描述说:Integer 类在对象中包装了一个基本类型 int 的值。 此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法。

A:成员变量:【Field Summary】 静态常量值

  • a、public static final int MAX_VALUE int类型可表示的最大值
  • b、public static final int MIN_VALUE int类型可表示的最小值
  • c、public static final int SIZE int类型所占用的bit位数 32 bit = 4 byte
  • d、public static final int TYPE 代表原始类型int类实例
  • e、public static final int BYTES int类型所占用的byte位数 since JDK 1.8

B:构造方法:【Constructor Summary】

  • a、public Integer(int i) 使用int类型数值 i 创建一个Integer对象
  • b、public Integer(String s) throws NumberFormatException 使用String类型数值 s 创建一个Integer对象。如果给定的s包含无法转换的字符的话,就抛出NumberFormatException 异常。

C:成员方法:【Method Summary】

除了直接继承自Number的6个方法以及少数间接继承自Object的方法外,均为 static 方法(使用Integer类名直接调用)。

  • a、public int intValue() 获取封装在Integer对象中的int值(继承自Number)

  • b、public static int parseInt(String s) 将String类型解码为int类型值。(其实底层是 Integer.parseInt(s, 10);)

  • c、public static int parseInt(String s,int radix) throws NumberForMatException 将String类型按照指定进制radix解码为int类型值。如果String中包含有无法转化的字符,则抛出NumberFormatException异常。

  • d、public String toString() 将Integer对象转化为字符串(继承自Object)(其实底层是Integer.toString(int))

  • e、public static String toString(int i) 将int类型值转化为字符串(其实底层是Integer.toString(int i,int radix))

  • f、public static String toString(int i,int radix) 按照指定的进制radix将int类型值转化为字符串。(其中 radix 的值介于 [Character.MIN_RADIX,Character.MAX_RADIX],亦即是[2,36],最小的是二进制,最大是36进制,如果不在该区间之内,则radix默认是 10 。最小的边界二进制很好理解,最大的边界值是因为 0-9 和 a-z 一共36个)

  • g、public static Integer valueOf(int i) 以int类型值创建一个Integer对象

  • h、public static Integer valueOf(String s) throws NumberFormatException 将String类型值解析为int类型值,然后创建一个Integer对象。如果String中包含有无法转化的字符,则抛出NumberFormatException异常。(其实底层是 Integer.valueOf(parseInt(s, 10));也就是 Integer.valueOf(int))

  • i、public static Integer valueOf(String s,int radix) throws NumberFormatException 将String类型值按照指定的radix进制解析为int类型值,然后创建一个Integer对象。如果String中包含有无法转化的字符,则抛出NumberFormatException异常。(其实底层是 Integer.valueOf(parseInt(s, radix));也就是 Integer.valueOf(int))

D:常用编程技巧:【Art of Programming】

  • a、int与String的相互转

  • I、int --> String : 编码
    - (1)字符串拼接:String str = "" + num;
    - (2)借助Integer方法:Integer.toString(int i[, int radix])(推荐使用)、new Integer(int i).toString()(已存在Integer对象 integer 时使用)(如果先使用int创建对象Integer,在调用方法toString方法得到字符串,性能差)
    - (3)借助String方法:String str = String.valueOf(int i)(极力推荐使用

  • II、String --> int : 解码
    - (1)已存在使用String作为参数创建的Integer对象:new Integer(String s).intValue()
    - (2)调用静态解析方法:Integer.parseInt(String s[,int radix])

注意:进制radix的存在是一个约束,当给定了进制的时候,则 int 或 String 中只能存在着 [0 , radix-1] 之间的字符,否则抛出 NumberFormatException 异常。

PS:其他继承自Number的最终类Byte、Short、Long、Float、Double与Integer类像似!

注意:方法源码的分析、模仿

示例:分析ValueOf方法的源码

public final class Integer extends Number implements Comparable<Integer>
{
	private final int value;

	public Integer(int value)
	{
		this.value = value;
	}

	public Integer(String s) throws NumberFormatException
	{
		this.value = parseInt(s, 10);
	}
	
	public static Integer valueOf(int i)
	{
		if (i >= IntegerCache.low && i <= IntegerCache.high)
			return IntegerCache.cache[i + (-IntegerCache.low)];
		return new Integer(i);
	}

	public static Integer valueOf(String s) throws NumberFormatException
	{
		return Integer.valueOf(parseInt(s, 10));
	}

	public static Integer valueOf(String s, int radix)
			throws NumberFormatException
	{
		return Integer.valueOf(parseInt(s, radix));
	}

	/**
	 * Cache to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive) as required by JLS.
	 * The cache is initialized on first usage. The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. During VM initialization, java.lang.Integer.IntegerCache.high property may be set and saved in the private system properties in the sun.misc.VM class.
	 */

	private static class IntegerCache
	{
		static final int low = -128;
		static final int high;
		static final Integer cache[];

		static
		{
			// high value may be configured by property
			int h = 127;
			String integerCacheHighPropValue = sun.misc.VM
					.getSavedProperty("java.lang.Integer.IntegerCache.high");
			if (integerCacheHighPropValue != null)
			{
				try
				{
					int i = parseInt(integerCacheHighPropValue);
					i = Math.max(i, 127);
					// Maximum array size is Integer.MAX_VALUE
					h = Math.min(i, Integer.MAX_VALUE - (-low) - 1);
				} catch (NumberFormatException nfe)
				{
					// If the property cannot be parsed into an int, ignore
					// it.
				}
			}
			high = h;

			cache = new Integer[(high - low) + 1];
			int j = low;
			for (int k = 0; k < cache.length; k++)
				cache[k] = new Integer(j++);

			// range [-128, 127] must be interned (JLS7 5.1.7)
			assert IntegerCache.high >= 127;
		}

		private IntegerCache() { }
	}
}

(3)、JDK 5 新特性:自动拆装箱

定义:

  • a、自动装箱(autoboxing):基本类型向类类型的自动转换
  • a、自动拆箱(auto-unboxing):类类型向基本类型的自动装换

示例:使用XJad反编译下面代码的字节码文件

class Demo
{
	public static void main(String args[])
	{
		Integer ii = 100;
		ii += 200;
		System.out.println("ii:"+ii);
	}
}

反编译结果:

import java.io.PrintStream;

class Demo
{
	Demo() { }

	public static void main(String args[])
	{
		Integer ii = 100;
		/** 反编译结果如下:很容易看得出来是 从基本类型到类类型的自动装箱(auto-boxing) */
		/** Integer integer = Integer.valueOf(100); */
		ii += 200;
		/** 反编译结果如下:很容易看得出来是 显示从类类型到基本类型的自动拆箱(auto-unboxing) 之后是 从基本类型到类类型的自动装箱(auto-boxing)*/
		/** integer = Integer.valueOf(integer.intValue() + 200); */
		System.out.println("ii:"+ii);
		/** 反编译结果如下: 
		 *  System.out.println((new StringBuilder()).append("ii:").append(integer).toString()); */
	}
}

面试题

1、分析代码以下代码:(解答在上面)

class Demo
{
	public static void main(String args[])
	{
		Integer ii = 100;
		ii += 200;
		System.out.println("ii:"+ii);
	}
}

2、输出以下代码的结果:

class Demo
{
	public static void main(String args[])
	{
		Integer i1 = 127
		Integer i2 = 127
		Integer i3 = 128
		Integer i4 = 128
		System.out.println(i1 == i2);
		System.out.println(i1.euqals(i2));
		System.out.println(i3 == i4);
		System.out.println(i3.euqals(i4));
	}
}

>>> true
    true
    false
    true

解答:

  • 针对 -128~127 之间的数据,Integer定义了一个私有静态的内部类Integer$IntegerCache,并在内部类中创建了一个数据缓冲池static final Integer cache[],如果数据在此范围内,则直接返回,并不会申请新的空间(创建对象)。(参看 示例:分析valueOf方法的源码)

结论:

  • Integer的数据直接赋值(若数值在 -128~127 之间,会直接从缓冲池中返回)。

推论:

  • a、Byte、Short、Long 和 Integer 一样,拥有缓冲池,并且数值范围也是 -128~127 之间直接返回;
  • b、Character 则同样拥有一个私有静态内部类,并针对 0~127 之间的字符在内部类中创建了一个数据缓冲池static final char cache[],若数据在这个范围内,则直接返回;
  • c、Boolean 则是只有两个值,没有缓冲池,是true就返回true,是false就返回false,不会申请任何空间,直接返回;
  • d、Float、Double 则没有这样的内部类,更不可能存在着缓冲池了。

附属1、 valueOf(Byte b) 方法 和 内部类源码:

public static Byte valueOf(byte b)
{
    final int offset = 128;
    return ByteCache.cache[(int)b + offset];
}

private static class ByteCache 
{
	private ByteCache(){}
	static final Byte cache[] = new Byte[-(-128) + 127 + 1];

	static
    {
	    for(int i = 0; i < cache.length; i++)
	        cache[i] = new Byte((byte)(i - 128));
	}
}

附属2、 valueOf(Boolean) 方法 源码:

public static Boolean valueOf(boolean b) 
{
	return (b ? TRUE : FALSE);
}

附属3、 valueOf(Character c) 方法 和 内部类源码:

public static Character valueOf(char c) 
{
	if (c <= 127) 
	{ // must cache
		return CharacterCache.cache[(int)c];
	}
	return new Character(c);
}
private static class CharacterCache 
{
	private CharacterCache(){}
	static final Character cache[] = new Character[127 + 1];
	static 
	{
		for (int i = 0; i < cache.length; i++)
			cache[i] = new Character((char)i);
	}
}

(4)、Character 类

在刚刚涉及到String的获取功能时,提供了一个案例:统计字符串中大小写字符和数字以及其他字符的个数。利用String获取功能中的length、charAt、indexOf、lastIndexOf、substring以及判断功能contains,再加上转换功能中的toLowerCase、toUpperCase,给出了三个版本的实现,但是随着这些不同的实现我们慢慢意识到可能已经写的够多了,可以想办法去偷懒了,这就要借助我们的偷懒神奇 - API帮助文档。在我们想要对一串字符进行判断的时候,API 为String类提供了判断功能,它们判定了字符串之间的包含关系、相等关系,以及字符串自身的相关属性。那么如果操作的对象变成了一个字符的话,API 又会提供什么类去封装 什么样的属性和行为,留给我们区使用呢?这就是 Character 类。(String类的底层实现是字符数组,也就是字符的集合)

0:java.lang包下的Character,使用时,不需要导包。描述说:Character 类在对象中包装一个基本类型 char 的值。Character 类型的对象包含类型为 char 的单个字段。 此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,反之亦然。

A:成员变量:【Filed Summary】 太多,不要求,需要的时候再去看。

B:构造方法:【 Constructor Summary】 仅仅存在一个包装char值得构造方法 public Character(char value),创建对象时,Character c = new Character(char),还有一种简化的方式 Character c = char; (底层原理是Character.valueOf(char) 以类型为char的值创建一个Character对象)

C:成员方法 【Method Summary】:参照操作字符串的String类成员方法分类方式

除了少数接继承自Object的方法外,均为 static 方法(使用Integer类名直接调用)。

  • a、Character 类的判断功能

    • (1)public static boolean isDigit(char ch) 判断指定字符是否为数字
    • (2)public static boolean isLetter(char ch) 判断制定字符是否是字母
    • (3)public static boolean isLowerCase(char ch) 判断制定字符是否是小写字母
    • (4)public static boolean isUpperCase(char ch) 判断制定字符是否是大写字母
    • (5)public static boolean isWhitespace(char ch) 判断指定字符是否为空白字符(‘\n’、‘\t’、‘\r’)
  • b、Character 类的获取功能(仅有一个)

    • (1)public static Character valueOf(char c) 包装指定char值,创建一个Character对象
  • c、Character 类的转换功能

    • (1)public static char toLowerCase(char ch) 将指定字符转换为小写
    • (2)public static char toUpperCase(char ch) 将指定字符转换为大写
    • (3)public static String toString(char c)将指定字符转换为字符串
    • (4)public String toString(char ch) 将指定字符转换为字符串(继承自Object)

重构-示例:统计大小写字符和数字以及其他字符在字符串中出现的次数

package com.rupeng.wrapper;

public class CharDemo
{
	public static void main(String[] args)
	{
		String str = "Hello, rp_12306@rupeng.com ! Welcome to Rupeng. "
				+ "Let's play game -- \"Guess number\".";
		int numCount = 0;
		int chrCount = 0;
		int otherCount = 0;
		char[] chs = str.toCharArray();
		for (int i = 0; i < chs.length; i++)
		{
			if (Character.isDigit(chs[i]))
			{
				numCount++;
			} else if (Character.isLetter(chs[i]))
			{
				chrCount++;
			} else
			{
				otherCount++;
			}
		}
		System.out.println(numCount);
		System.out.println(chrCount);
		System.out.println(otherCount);
	}
}

面试题

1、说说Java常量池?

常量池(方法区中):在编译时就可以确定的数据会被放在常量池中。常量池主要有下面的三个内容:(1)、存放类文件的信息:类名、包名、方法名、字段名和类型…;(2)、存放static final 字段(自定义常量);(3)、7类常量池:字符串和6个基本类型(不包含Float和Double)的包装类的内容。

2、* 疯狂的正则表达式 *

通过上述常用类的学习,我们来看一下下面的需求:

检验一个QQ号码的正确性。要求:(1)长度是5到15位;(2)不可以以0开头;(3)只含有数字

获悉需求之后,通过分析给出以下代码:

示例:QQ号的检验程序!

package com.rupeng.wrapper;

import java.util.Scanner;

/**
 * 需求:检验QQ号的合法性。出现不合法就予以提示 
 * 			 要求:(1)长度是5到15位;(2)不可以以`0`开头;(3)只含有数字
 * 
 * 分析:将QQ号使用String字符串进行接受,方便判断; 
 * 				当出现以上任何一个是不满足的,就给出对应提示信息
 * 
 * 编码:在进行编码的时候,先是基于功能的去实现,不考虑具体的优化。
 * 				但是请注意一件事情:上面这些条件并不是彼此之间互斥(如果使用基本的if...return是不合理的)
 * 				 诸如:(先考虑前两个条件)
 * 				if(length<5||length>15)
 * 				 {
 * 					 out("length is not legal"!);
 * 					 return;
 * 				 }
 * 				 if(firstChar	== '0')
 * 				 {
 * 					 out("firstChar is not legal"!);
 * 					 return;
 * 				 }
 * 咋一看可能觉得是一个结构比较好的程序。但是试着这样的输入 0122(长度不够且以0开头)
 * 		但是给出的提示只是第一个,因为return的关系,以0开头这个问题的提示被屏蔽了。
 *  也就是说这段代码对于基本的功能都没有完成。(基础都没有)
 * 
 * @author Joian
 */
public class QQDemo
{
	public static void main(String[] args)
	{
		System.out.println("Please enter your QQ number: ");
		String QQ = new Scanner(System.in).nextLine();
		if (QQ == null)
		{
			System.out.println("Null");
			return;
		}

		if (QQ.length() < 5 || QQ.length() > 15)
		{
			System.out.println("Length of QQ number is not legal !");
			return;
		}
		for (int i = 0; i < QQ.length(); i++)
		{
			char chr = QQ.charAt(i);
			if (i == 0 && chr == '0')
			{
				System.out.println("Not in the beginning of character 0.");
				return;
			}
			if (chr < '0' || chr > '9')
			{
				System.out.println("Cannot Contain any non numeric characters");
				return;
			}
		}
		System.out.println("QQ number is valid !");
	}
}

功能完整性改进-示例:QQ号的检验程序!

package com.rupeng.wrapper;

import java.util.Scanner;

public class QQDemo2
{
	public static void main(String[] args)
	{
		System.out.println("Please enter your QQ number: ");
		String QQ = new Scanner(System.in).nextLine();
		if (QQ == null)
		{
			System.out.println("Null");
			return;
		}
		int count = 0;
		String[] msg = new String[] { "Length of QQ number is not legal !",
				"Not in the beginning of character 0.",
				"Cannot Contain any non numeric characters" };
		if (QQ.length() < 5 || QQ.length() > 15)
		{
			count++;
		}
		for (int i = 0; i < QQ.length(); i++)
		{
			char chr = QQ.charAt(i);
			if (i == 0 && chr == '0')
			{
				count++;
			}
			if (chr < '0' || chr > '9')
			{
				count++;
			}
		}
		if (count == 0)
		{
			System.out.println("QQ number is valid !");
		} else
		{
			for (int i = 0; i < (count < 3 ? count : 3); i++)
			{
				System.out.println(msg[i]);
			}
		}
	}
}

上面的代码实现太过于繁琐,如果说可以通过一定的规则在实现上会不会更加的easy呢,于是我们在API探索到了“正则表达式”。

先来看看它的强大之处,对于QQ号的检验:

package com.rupeng.wrapper;

import java.util.Scanner;

public class QQDemo3
{
	public static void main(String[] args)
	{
		System.out.println("Please enter your QQ number: ");
		String QQ = new Scanner(System.in).nextLine();
		if (QQ == null)
		{
			System.out.println("Null");
			return;
		}
		String regex = "[1-9][0-9]{4,14}";
		boolean flag = QQ.matcher(regex);
		if(!falg)
		{
			System.out.println("QQ number is not legal");
		}
		else
		{
			System.out.println("QQ number is legal");
		}
	}
}

String类的成员方法:

  • public boolean matches(String regex) 判断当前字符串是否满足给定的正则表达式regex 。 调用此方法的str.matches(regex)形式与以下表达式的结果完全相同:Pattern.matches(regex,str)。 若给定的正则表达式无效的话,抛出 PatternSyntaxException 。 since JDK 1.4

A:正则表达式的组成规则

规则字符在java.util.regex.Pattern -public final class Pattern extends Object implements Serializable中,具体的规则如下:

  • a、字符
构造匹配
x字符 x (任意字符表示其本身,例:‘a’)
\\反斜杠字符 ‘’
\t制表符 ‘\u0009’
\n换行符 ‘\u000A’
\r回车符 ‘\u000D’
  • b、字符类
构造匹配
[abc]字符 a、b、c中的一个(简单类)
[^abc]除了字符 a、b、c外的任意一个字符(否定)
[a-zA-Z]a-z或者A-Z中的字符 含端点字符(范围)
[0-9]0-9范围内的数字字符(范围)
[a-d[m-p]]等价 [a-dm-p] 并集
[a-z&&[def]]交集
[a-z&&[^bc]]差集
[a-d[^m-p]]差集
  • c、预定义字符类
构造匹配
.任意字符("\\.“表示”."本身)
\d数字0-9:[0-9] “\d”
\D非数字0-9:[^\d] “\D”
\w单词字符:[a-zA-Z_0-9] “\w”
\W非单词字符:[^\w] “\W”
\s空白字符:[ \t\n\x0B\f\r] “\s”
\S非空白字符:[^\s] “\S”
  • d、边界字符
构造匹配
^行的开头
$行的结尾
\b单词边界
\B非单词边界
  • e、Greedy数量词
构造匹配
X?X,一次或一次也没有
X*X,零次或多次
X+X,一次或多次
X{n}X,恰好 n 次
X{n,}X,至少 n 次
X{n,m}X,至少 n 次,但是不超过 m 次
所有的量词都是贪婪的,会尽量多的匹配 eg:"g+" 匹配 "aggge" 中的 "ggg"防止贪婪行为的做法:使用 "g+?" 即可将量词匹配变得懒惰,匹配 "aggge" 时只是 "g"
  • f、Logical运算符
构造匹配
XYX 后跟 Y
X|YX 或 Y
(X)X,作为捕获组

在这里插入图片描述
捕获组 0 永远是表达式本身的匹配。


B:正则表达式的应用

  • a 、String类成员方法:判断功能(9) public boolean matches(String regex) 判断指定字符穿是否满足正则表达式regex

示例:用户名的验证。类似 :rp_xxx@rupeng.com(其中xxx是指1或多个字符)

String regex = "rp_[^_]\\w+@rupeng.com";

// sspu学校邮箱验证的正则表达式
String mailregex = "\\w+@sspu\\.((com)|(cn))";
  • b 、String类的成员方法:转换功能(18) (也可称为分割功能)pubic String[] split(String regex) 根据给定的正则表达式 regex 拆分字符串,得到字符串数组
  • 作用:使用给定的表达式和限制参数 0 来调用两个参数的 split 方法 public String[] split(String regex,int limit) limit 参数控制模式应用的次数,n 为 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。

例如,字符串 “boo:and:foo” 使用这些参数可生成以下结果:

Regex结果
:{"boo","and","foo"}
o{"b","",":and:f"}

示例1:数据库查找年龄段“18-24”之间的人员

// 实际开发中年龄段因该是文本列表框的一个子项,
// 通过获取子项的值,再进行分割,就可以传入数据库查询
String ageStr = "18-24";
String[] age = ageStr.split("-");
int startAge = Integer.parseInt(age[0]);
int endAge = Integer.parseInt(age[1]);

// 数据库中查询年龄在 18-24岁 之间的人员信息
String sql = "SELECT * FROM employee WHERE age BETWEEN " + startAge + " AND " + endAge;

示例2:给定输入:“91 27 46 38 50”,按照升序排序输出

/** 第一种解决方案 */
package com.rupeng.wrapper;

import java.util.Arrays;

public class SortDemo1
{
	public static void main(String[] args)
	{
		String inStr = "91 27 46 38 50";
		String regex = " ";
		String[] outStrs = inStr.split(regex);
		Arrays.sort(outStrs);
		StringBuilder out = new StringBuilder();
		for (int i = 0; i < outStrs.length; i++)
		{
			out.append(outStrs[i]).append(" ");
		}
		System.out.println(out.toString());
	}
}

/** 第二种解决方案 */
package com.rupeng.wrapper;

import java.util.Arrays;

public class SortDemo2
{
	public static void main(String[] args)
	{
		String inStr = "91 27 46 38 50";
		String regex = " ";
		String[] outStrs = inStr.split(regex);
		int[] outInt = new int[outStrs.length];
		for (int i = 0; i < outInt.length; i++)
		{
			outInt[i] = Integer.parseInt(outStrs[i]);
		}
		Arrays.sort(outInt);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < outInt.length; i++)
		{
			sb.append(outInt[i]).append(" ");
		}
		System.out.println(sb.toString());
	}
}
  • c、 String类的成员方法:替换功能(3)public String replaceAll(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 调用此方法的 str.replaceAll(regex, repl) 形式与以下表达式产生的结果完全相同:Pattern.compile(regex).matcher(str).replaceAll(repl)

示例:给定字符串 str = “helloqq10000java”,分别实现不同需求

/** 需求1:将所有数字都是用"*"代替 */
package com.rupeng.wrapper;

public class NumDemo1
{
	public static void main(String[] args)
	{
		String str = "helloqq10000java";
		/** regex = "[0-9]" */
		String regex = "\\d";
		str = str.replaceAll(regex, "*");
		System.out.println(str);
	}
}

/** 需求2:将所有数字用一个"*"代替 */

/** regex = "[0-9]+" */
String regex = "\\d+";
str = str.replaceAll(regex, "*");

/** 需求3:去除所有数字 */

/** regex = "[0-9]+" */
String regex = "\\d+";
str = str.replaceAll(regex, "");

P.S.
$ 符号在正则表达式中的使用
正则中可以使用 () 将一个表达式代表一个组,每一个组在表达式中都用对应的引用值,整个表达式默认是第 0 组,所以自己声明的组需要从 1 开始,譬如:第1组表示为 \\1。(如果不从 1 开始,可能没有任何的效果,也可能抛出异常)
$ 用来引用一个组 (),组号从1开始;格式:$组号

String str = "abbbbbbbbcgggggggkjjjjjjji";
// 需求:连续重复的字符只显示一次
String repStr = str.replaceAll("([a-z]\\1+)","$1");
  • d、获取功能

模式:Pattern类 *

public final class Pattern extends Object implements Serializable

0:java.util.regex包下的Pattern类,描述说:Pattern是正则表达式的编译表示形式。指定为字符串的正则表达式必须先编译为此类的实例。然后,将得到的模式实例用于创建Matcher对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有的状态都保留在匹配器中,所以多个匹配器可以使用同一个模式。

因此,典型的调用顺序是:

Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(srcStr);
boolean b = m.matches();

在仅使用一次正则表达式时,可以方便地通过Pattern类的matches方法的。此方法编译的表达式并在单个调用中将输入的序列与其匹配。

boolean b = Pattern.matches(regex,srcStr);

等价于上面的三个语句,但是对于重复的匹配而言,它的效率不高。因为每次进行匹配的时候,都需要从头开始,编译模式、构造匹配器、进行匹配,而使用上面三条语句,则每次只需要重置匹配器或构造新的匹配器,即可进行匹配,不用再次编译模式。故此,效率低最终原因就是:无法重用已编译的模式。

Pattern类的实例是不可变的,可供多线程安全的访问。Matcher类的实例应用于此则不安全。

Pattern类是正则表达式的编译表示形式。通过上面的实现,可以有一个简单猜测:所有关于正则表达式的匹配问题都包括以下几个步骤:

  • (1)依据给定的正则表达式regex,编译创建Pattern模式对象;
  • (2)使用创建的模式对象,构造一个或多个Matcher匹配器对象;
  • (3)使用给定的字符序列进行匹配,匹配的所有状态存放在每一个匹配器对象中;
  • (4)根据需求,调用所需状态值。

总结以上所有关于正则表达式功能方法:
在这里插入图片描述
A:成员变量:【Field Summary】

B:构造方法:【Constructor Summary】 私有构造,模式实例通过静态方法compile编译创建

C:成员方法:【Method Summary】

  • a、 public static Pattern compile(String regex) 将正则表达式编译到模式中。默认的匹配标志符 0;当regex不符合正则表达式的规则时,抛出PatternSyntaxException异常 。底层调用的是:私有构造方法 new Pattern(regex, 0)

  • b、public static Pattern compile(String regex,int flags) 将正则表达式编译到给定匹配标识符flags的模式中。当regex不符合正则表达式的规则时,抛出PatternSyntaxException异常 。底层调用的是:私有构造方法 new Pattern(regex, flags)

  • c、public int flags() 返回此模式的匹配标志

  • d、public Matcher matcher(CharSequence input) 创建 给定输入与此模式的匹配器。若尚未编译,先进行同步编译,然后使用 Matcher m = new Matcher(this, input); 获取匹配器

  • e、public String pattern() 返回编译到此模式的正则表达式

  • f、public String[] split(CharSequence input) 根据围绕此模式的匹配来拆分给定字符序列后,得到字符串数组。是String类的成员方法 public String[] split(String regex) 底层的实现原理。其实际调用的是split(input,0)

  • g、public String[] split(CharSequence input,int limit) 是 split 方法最底层的实现,其他的split实现都是直接或者间接得调用此功能实现的。

匹配器:Matcher类 *

public final class Matcher extends Object implements MatchResult since JDK 1.4

0:Matcher类在java.util.regex包下,描述说:Matcher匹配器是通过解释Pattern模式对字符序列执行匹配操作的引擎。通过调用Pattern模式 matcher 方法创建匹配器实例。创建的匹配器实例可以通过以下三种方式进行匹配:

  • matches 方法尝试将整个输入字符序列与该模式匹配
  • lookingAt 方法尝试将整个输入字符序列从头开始与该模式匹配。当且仅当输入字符序列的前缀和匹配器匹配时,返回 true 。
  • find 方法扫描输入字符序列以查找与该模式匹配的下一个子序列。当且仅当输入字符序列的子序列与匹配器匹配时,返回 true 。

每个方法都返回一个表示成功或失败的bolean值。通过查询匹配器的状态可以获取关于成功匹配的更多信息。

可以通过调用匹配器的 reset() 方法来显示重置匹配器,若需要重新给定输入字符序列,则可以通过调用其 reset(CharSequence)方法。重置匹配器将放弃其显式状态信息并将添加位置设置为零。

此类实例应用多线程不安全。

A:成员变量:【Field Summary】

B:构造方法:【Constructor Summary】 仅仅存在私有构造方法,由Pattern类的matcher方法调用创建Matcher实例

C:成员方法:【Method Summary】

  • a、public boolean matches() 匹配整个输入字符序列

  • b、public boolean lookingAt() 匹配输入字符序列的前缀

  • c、public boolean find() 匹配整个字符序列的子序列

  • d、public Matcher reset() 重置匹配器

  • e、public Matcher reset(CharSequence input) 重置匹配器,给定新的输入字符序列

  • f、public Pattern pattern() 返回由此匹配器解释的模式。 注意:Pattern类中的同名方法public String pattern()返回的是用于构建模式的正则表达式(字符串)

  • g、public String replaceAll(String replacement) 替换模式与给定替换字符串相匹配的输入序列的每个子序列。是 String类中 replace 系列方法的最底层原理。

继承自接口 MatchResult 的有关状态信息的三个主要方法:

  • h、public int start([int group]) 返回上次匹配的 group 的初始索引。当 int group 不提供时,实际是调用的 start(0)

    • int group :匹配模式中捕获组的索引
  • i、public int end([int group]) 返回 上次匹配的 group 的偏移量;如果匹配成功但组本身没有任何匹配项,则返回 -1。 int group 不提供时,实际是调用的 end(0)

  • j、public String group([int group]) 返回由上次匹配操作所匹配的输入字符序列的子序列。int group 不提供时,实际是调用的 group(0)

注意:以上,必须在匹配操作进行之后,才能获取。否则抛出异常

  • IllegalStateException : No Match Found 【表示没有进行任何的匹配操作,或者上次匹配操作失败】

  • IndexOutOfBoundsException : Illegal start index 【给定索引的模式中不存在捕获组】

实例:获取给定字符串中长度为8的专有单词(也就是说大写字符开头)

package com.rupeng.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo
{
	public static void main(String[] args)
	{
		String info = "Hello, everyone ! I am Joian Sun."
				+ " I come from Fuyang City, Anhui Province. "
				+ "Currently studying at Shanghai Second Polytechnic University, "
				+ "Software Engineering. ";
		String regex = "\\b[A-Z]\\w{7}\\b";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(info);
		while (m.find())
		{
			System.out.println(m.group());
		}
	}
}

面试题

1、硬盘上的路径 “E:\com\rupeng\java” ,获取盘符和各级文件夹名称。

解答:

String link = "E:\\com\\rupeng\\java";
String regex = "\\\\";
String[] dirs = link.split(regex);

3、数学工具类:Math

0:类的引入及其描述

java.lang包下的Math类,包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。

A:成员变量【Field Summary】

  • public static final double E 自然对数底数 e
  • public static final double PI 圆周率 π

B:构造方法【Constructor Summary】

仅仅存在私有的构造方法,因是工具类不需要实例化

C:成员方法【Method Summary】

主要针对四种基本类型(int、long、float、double )的部分实用功能

  • a、public static double ceil(double d) 向上取整;注意:Math.ceil(x) 的值与 -Math.floor(-x) 的值完全相同。 (亦即 互为相反数的正浮点数向上取整的值和负浮点数向下取整的值相同)

  • b、public static double floor(double d) 向下取整

  • c、public static long round(double d) 返回最接近 d 的 long 值;结果等于 (long)Math.floor(d + 0.5d)

  • d、public static int round(float f) 返回最接近 f 的 int 值;结果等于 (int)Math.floor(f + 0.5f)

  • e、public static double random() 返回在[0.0,1.0)之间的随机数。第一次使用时创建一个伪随机数类Random的对象 new java.util.Random()

示例:随机生成[1,100]之间的任意正整数

int num = (int)(Math.random() * 100) + 1;

面试题

1、请阐述 round 实现四舍五入的原理

解答:简言之,任意数加上0.5,然后向下取整

(int)Math.floor(num + 0.5f);  // float类型的四舍五入
(long)Math.floor(num + 0.5d);  // double类型的四舍五入

2、设计一个方法,可以实现获取任意范围内的随机数

public static int getRandom(int low,int high)
{
	return (int)(Math.random() * (high - low + 1)) + low;
}

4、伪随机数:Random类

0:类的引入及其描述

java.util包下的Random类,主要用于产生伪随机数流

A:成员变量【Field Summary】

没有

B:构造方法【Constructor Summary】

  • public Random() 没有给定种子,创建Random的实例,默认的种子值是当前时间的毫秒数。每次产生的随机数不定

  • public Random(long seed) 给定seed种子值,每次产生的随机数和第一次的相同

Random rnd = new Random(seed);
// 相当于:
Random rnd = new Random();
rnd.setSeed(seed);  // 设置种子值

C:成员方法:【Method Summary】

主要说明int相关得成员方法,其他的类似

  • public int nextInt() 返回 int 范围内的随机数
  • public int nextInt(int n) 返回 [0,n) 范围内的随机数
  • public void setSeed(long seed) 使用单个 long 种子设置此随机数生成器的种子

重写示例:获取[1,100]范围内的随机数

public static int getRandom(int low,int high)
{
	return new Random().nextInt(100)+1
}

但是如果是要获取指定范围内的随机数的话,就没有那么容易了,并且很多应用程序发现Math.random()方法更易使用。

PS:建议使用 Math.random()方法 实现随机数的获取 !


小总结:

在这里插入图片描述


JavaSE基础传智播客毕向东老师全程笔记PDF JavaSE基础传智播客毕向东老师全程笔记 立即下载

相关推荐

浅谈javaSE GUI (Action事件)

下面小编就为大家带来一篇浅谈javaSE GUI (Action事件)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

Gui的三种布局方式

public static void main(String[] args){ //标题 Frame myFrame = new Frame("Hello World"); //设置可见性 myFrame.setVisible(true); //设置窗口大小 //myFrame.setSize(300, 300); //设置颜色 myFrame.setBackground(Color.BLUE); //RGB颜色 myFrame.setBackground(new.

weixin_45731448的博客 1157

MacOS M芯片部署ComfyUI:从环境排雷到插件生态一站式指南

本文为MacOS M系列芯片用户提供了一份详尽的ComfyUI部署指南。文章深入剖析了因架构差异导致的常见安装报错根源,并给出了基于MPS后端的正确PyTorch安装命令。从创建纯净Python虚拟环境、分步安装依赖,到验证GPU加速,手把手指导完成部署。同时,还推荐了包括管理器、汉化在内的必备插件,以完善使用生态,帮助用户一站式解决从环境搭建到效率提升的所有问题。

weixin_29261711的博客 994

嵌入式学习文章推荐+资料下载

2129

Nordic BLE芯片RF测试

BLE设备在过蓝牙BQB,FCC,ETSI等各种认证时实验室一般都需要做RF各项指标的测试。Nordic公司的SDK包中提供了两种RF测试程序,一种是DTM,另一种是Radio test。这两种都可以做RF指标测试但各自又有区别。DTM是按照蓝牙规范中Direct test mode所要求数据格式测试(数据格式定义参看:Bluetooth Core Specification v5.0->...

5639

NPP/VIIRS夜间灯光数据:从下载到应用的完整指南

本文提供了NPP/VIIRS夜间灯光数据从下载、处理到应用的完整实战指南。详细介绍了如何从官方源获取数据、解读文件结构、进行坐标校正与数据清洗,并深入探讨了其在城市扩张监测、社会经济指标估算、重大事件影响评估等领域的核心应用。文章旨在帮助研究者与从业者快速掌握这一强大的空间数据,将其转化为研究中的实用工具。

gpu4optimizer的博客 866

IntellIJ IDEA 配置 Maven 以及 修改 默认 Repository(转)

IDEA版本: IntelliJ IDEA 2017.2 Build #IU-172.3317.76, built on July 15, 2017 Licensed to Administrator JRE: 1.8.0_152-release-915-b5 amd64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Windows 7 6....

xiaoguigui520的专栏 703

第8.1节 满足构网要求的功率器件与散热设计

摘要: 构网型变流器的功率器件选型与散热设计面临严苛要求,需综合考虑过载能力、暂态应力与可靠性。IGBT模块选型需重点评估电压/电流等级、损耗特性及结温波动,而SiC MOSFET虽具有高频低损耗优势,但面临栅极可靠性等挑战。散热设计需采用液冷等先进技术控制结温波动,并通过电热应力仿真和寿命预测实现可靠性优化。系统化选型流程需结合规范要求、工况谱分析和实测验证,为构网型变流器提供坚实的物理基础。

技术工作者 914

javase 04 常用类

04 常用类 Object Object类位于java.lang包中,java.lang包包含着Java最基础和核心的类,在编译时会自动导入;Object类是所有Java类的根基类,如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类 包装类 JAVA并不是纯面向对象的语言。Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的。但是我们在实际使用中经常需要将基本数据转化成对象,便于操作。比如:集合的操作中。例如使用Map对象要操作put()方法时,需要传

皮皮亮的博客 534

基于Matlab生成并可视化多架飞机轨迹仿真(附源码)

这使我们可以轻松地对直线和恒定转弯进行建模,并具有额外的自由度,可以在直线段和曲线段之间平滑过渡。同样,空气中的物体会经历重力的影响,遵循抛物线(二次)路径。需要更多的航点来适应这些变化,但是轨迹的其余部分需要更少的点。第三个轨迹,如下所示,代表了一架速度更高的飞机。它由两个恒定的转弯组成,飞机在第二个转弯的中间减速。一旦知道(并设置了)物体穿过空间的物理路径,物体的速度作为行进距离的函数就通过三次埃尔米特插值来确定。在此示例中,学习了内部使用的插值符背后的概念,并展示了如何使用少量航点重现场景。

珞瑜的博客 5464

Dify平台隐患url:/console/api/remote-files/upload暴露高危漏洞,配置nginx htpasswd模块认证机制屏蔽解决

内部网络探测: 攻击者可通过SSRF扫描内网服务云元数据访问: 可能访问AWS/Aliyun/腾讯云等元数据服务服务端请求伪造: 以服务器身份发起任意HTTP请求。

CN_Eden 1318

【JavaSE学习】05-1常用API

JavaSE(B站黑马)学习笔记 05-1常用API

weixin_48074431的博客 1162

基于YOLOv10的微小目标检测,多头检测器提升小目标检测精度

引入多头检测器助力YOLOv10,暴力提升小目标检测性能

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 2569

JavaSE部分 ( 常用API )

JavaSE部分 ( 面向对象 常用API) 匿名对象 概念 匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。 eg :new 类名称(); 注意事项:匿名对象只能使用唯一的一次,下次再用不得不再创建一个新对象。 使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象。 应用 匿名对象与Scanner 匿名对象传参 匿名对象作为返回值 package fill; import java.util.Scanner; public class Anonymous_02 {

QuantumYou的博客 371

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

JavaSE学习 day04

今天,我首先继续学习了JavaSE库存管理,继续学习了用户登录。 然后,进行了阶段复习。 复习了javase开发工具,计算机储备知识,java基础知识,jdk操作,jdk下载安装以及配置,notepad16进制,第一个Java程序,Java API文档,eclipse实操,Java基本语法,进制。 常用的DOS命令: dir 列出当前目录下的文件以及文件夹 md 创建目录 rd 删除目录 删除文件夹 cd 进入指定目录 cd … 退回到上一级目录 cd\ 退回到根目录 del 删除文件 exit 退出

m0_49528461的博客 178

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

使用SimpleDateFormat类,把2018-03-04转换为2018年03月04日

使用SimpleDateFormat类,把2018-03-04转换为2018年03月04日 package homework; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class One { public static void main(String[] args) throws P

m0_51383338的博客 729

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

刘意JavaSE 学习笔记——总纲

开始学习JavaSE了,记录下自己学习的进程。   学习大纲   1 开发环境配置 day01 配置 2 基础语法(基本差不多,看一下就好) day02 命名规则,进制转换 day03 运算符,if语句 day04 switch,for,while,break,continue,return语句 day05 方法 重载 一维数组 day06 二维数组 类,对象,内存解析 以...

desperatecat的博客 3851

JavaSE 笔记【七】Java常用类之日期时间API

视频链接:Java零基础教程 java.lang.System System类提供的 public static long currentTimeMillis() 用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差 此方法适于计算时间差 计算世界时间的主要标准有: UTC(Coordinated Universal Time) GMT(Greenwich Mean Time) CST(Central Standard Time) java.util.Date 表示特定的瞬间,精确到.

博客 238

JavaSE基础——第十一章 常用类(二)

本文总结了Java常用类,包括Math、Arrays、System、大数据处理类、日期类的常用方法

cherryc_的博客 879

JavaSE进阶04:API中常用工具类

系列文章目录 day01:Java概述和基础语法 文章目录系列文章目录MathSystemObjectObject类的toString方法Object类的equals方法equals()面试题Objects Math 1、Math类概述 Math 包含执行基本数字运算的方法 2、Math中方法的调用方式 Math类中无构造方法,但内部的方法都是静态的,则可以通过 类名.进行调用 3、Math类的常用方法 方法名 方法名 说明 public static int abs(in

XXXZhy丶Blog 711

【JavaSE学习】04-3Java高级(多线程、网络编程)

JavaSE(B站黑马)学习笔记 04-3Java高级(多线程、网络编程)

weixin_48074431的博客 1326

【JavaSE学习笔记】(四)常用类

如何创建对象并封装字符串数据:①直接放到双引号中 String name="X";②new String调构造器方法。

m0_73580478的博客 926

JavaSE[本人复习SE时的记录,适合已经学习完JavaSE的朋友复习回顾]

00基本语法文档注释变量分类运算符流程控制数组 文档注释 ①文档注释用javadoc来解析,在Dos中输入一下命令 ②javadoc -d (要生成的)文件夹的名字 -author -version 文件名(.java结尾的文件名) ③执行完命令后,会在当前的目录下创建一个文件夹,其中的index.html即为该程序的说明文档 变量分类 运算符 流程控制 数组 ...

ZZWDN_旺小白的博客 3083

javaSE常用类(二)—— 日期类

java常用类——日期类

qq_44886213的博客 487

Java基础复习(JavaSE高级)第二章:常用API

这一段代码:通过ZoneId.systemDefault();获取系统默认时区存入了zoneId中,不记得具体时区在哪可以调用getavailableZoneIds();获取全部时区的Id最后可以用ZoneId.of把某个时区id封装成ZOneId对象zoneId1.第一行代码中我们可以通过ZonedDateTime获取带有具体时区的该时区的时间。由于之前zoneId1的值中存储的是美国纽约的时区,这行代码的输出结果就是此时此刻纽约时区的时间。

qq_74196888的博客 1071
上一篇: 【PAT乙级】题解-1014 福尔摩斯的约会
下一篇: 【JavaSE基础】05-常用类API(三)
老坛算粉
博客等级 码龄12年 708粉丝 73原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老坛算粉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值