- 1、包装类(Wrapper Clas)
- (0)、包装类的引入及其描述
- (1)、Number 抽象类
- (2)、Integer 类 *
- (3)、JDK 5 新特性:自动拆装箱
- 面试题
- (4)、Character 类
- 面试题
- 2、`*` 疯狂的正则表达式 `*`
- A:正则表达式的组成规则
- B:正则表达式的应用
- 模式:Pattern类 *
- 匹配器:Matcher类 *
- 面试题
- 3、数学工具类:Math
- 0:类的引入及其描述
- A:成员变量【Field Summary】
- B:构造方法【Constructor Summary】
- C:成员方法【Method Summary】
- 面试题
- 4、伪随机数:Random类
- 0:类的引入及其描述
- A:成员变量【Field Summary】
- B:构造方法【Constructor Summary】
- C:成员方法:【Method Summary】
先来看一下以下两个主要的需求:
- 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大师们都给了,你凭什么不给。
-
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位数 sinceJDK 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=} 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’)
- (1)
-
b、Character 类的获取功能(仅有一个)
- (1)
public static Character valueOf(char c)
包装指定char值,创建一个Character对象
- (1)
-
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)
- (1)
重构-示例:统计大小写字符和数字以及其他字符在字符串中出现的次数
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);
}
}
面试题
2、1、说说Java常量池?
常量池(方法区中):在编译时就可以确定的数据会被放在常量池中。常量池主要有下面的三个内容:(1)、存放类文件的信息:类名、包名、方法名、字段名和类型…;(2)、存放static final 字段(自定义常量);(3)、7类常量池:字符串和6个基本类型(不包含Float和Double)的包装类的内容。
*
疯狂的正则表达式 *
通过上述常用类的学习,我们来看一下下面的需求:
检验一个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
。 sinceJDK 1.4
规则字符在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运算符
构造 | 匹配 |
---|---|
XY | X 后跟 Y |
X|Y | X 或 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+)","");
- d、获取功能
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实现都是直接或者间接得调用此功能实现的。
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
自然对数底数 epublic static final double PI
圆周率 π
仅仅存在私有的构造方法,因是工具类不需要实例化
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()
方法 实现随机数的获取 !
小总结:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)