首页 > 编程语言 > 详细

java基础学习(三)

时间:2021-04-03 20:11:12      阅读:17      评论:0      收藏:0      [点我收藏+]

Java基础学习(三)

十、正则表达式
十一、数字和日期

十、正则表达式

正则表达式(Regular Expression)又称正规表示法、常规表示法,在代码中常简写为 regex、regexp 或 RE,它是计算机科学的一个概念。

正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作,是一种可以用于模式匹配和替换的规范。一个正则表达式就是由普通的字符(如字符 a~z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。

String 类里也提供了如下几个特殊的方法。

  • boolean matches(String regex):判断该字符串是否匹配指定的正则表达式。
  • String replaceAll(String regex, String replacement):将该字符串中所有匹配 regex 的子串替换成 replacement。
  • String replaceFirst(String regex, String replacement):将该字符串中第一个匹配 regex 的子串替换成 replacement。
  • String[] split(String regex):以 regex 作为分隔符,把该字符串分割成多个子串。

上面这些特殊的方法都依赖于 Java 提供的正则表达式支持,除此之外,Java 还提供了 Pattern 和 Matcher 两个类专门用于提供正则表达式支持。

很多读者都会觉得正则表达式是一个非常神奇、高级的知识,其实正则表达式是一种非常简单而且非常实用的工具。正则表达式是一个用于匹配字符串的模板。实际上,任意字符串都可以当成正则表达式使用。例如“abc”,它也是一个正则表达式,只是它只能匹配“abc”字符串。

如果正则表达式仅能匹配“abc”这样的字符串,那么正则表达式也就不值得学习了。正则表达式作为一个用于匹配字符串的模板,将某个字符模式与所搜索的字符串进行匹配。本文简单了解一下如何使用正则表达式来操作字符串。

1.正则表达式支持字符

创建正则表达式就是创建一个特殊的字符串。正则表达式所支持的合法字符如表 1 所示。

字符 解释
X 字符x(x 可代表任何合法的字符)
\0mnn 八进制数 0mnn 所表示的字符
\xhh 十六进制值 0xhh 所表示的字符
\uhhhh 十六进制值 0xhhhh 所表示的 Unicode 字符
\t 制表符(“\u0009”)
\n 新行(换行)符(‘\u000A’)
\r 回车符(‘\u000D’)
\f 换页符(‘\u000C’)
\a 报警(bell)符(‘\u0007’)
\e Escape 符(‘\u001B’)
\cx x 对应的的控制符。例如,\cM匹配 Ctrl-M。x 值必须为 A~Z 或 a~z 之一。

除此之外,正则表达式中有一些特殊字符,这些特殊字符在正则表达式中有其特殊的用途,比如前面介绍的反斜线\

如果需要匹配这些特殊字符,就必须首先将这些字符转义,也就是在前面添加一个反斜线\。正则表达式中的特殊字符如表 2 所示。

所谓特殊字符:就是在正则表达式中就需要在前面加\,同样在java开发中还要加\,所以一共会加两个\,例如在正则表达式中有三个\,则在java中就要另加三个\

特殊字符 说明
$ 匹配一行的结尾。要匹配 $ 字符本身,请使用\$
^ 匹配一行的开头。要匹配 ^ 字符本身,请使用\^
() 标记子表达式的开始和结束位置。要匹配这些字符,请使用\(\)
[] 用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用\[\]
{} 用于标记前面子表达式的出现频度。要匹配这些字符,请使用\{\}
* 指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用\*
+ 指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用\+
? 指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用\?
. 匹配除换行符\n之外的任何单字符。要匹配.字符本身,请使用\.
\ 用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\字符,请用\\
| 指定两项之间任选一项。如果要匹配字符本身,请使用\|

将上面多个字符拼起来,就可以创建一个正则表达式。例如:

"\u0041\\" // 匹配 A
"\u0061\t" // 匹配a<制表符>
"\?\[" // 匹配?[

注意:可能大家会觉得第一个正则表达式中怎么有那么多反斜杠?这是由于 Java 字符串中反斜杠本身需要转义,因此两个反斜杠(\)实际上相当于一个(前一个用于转义)。

上面的正则表达式依然只能匹配单个字符,这是因为还未在正则表达式中使用“通配符”,“通配符”是可以匹配多个字符的特殊字符。正则表达式中的“通配符”远远超出了普通通配符的功能,它被称为预定义字符,正则表达式支持如表 3 所示的预定义字符。

预定义字符 说明
. 可以匹配任何字符
\d 匹配 0~9 的所有数字
\D 匹配非数字
\s 匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等
\S 匹配所有的非空白字符
\w 匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_
\W 匹配所有的非单词字符

上面的 7 个预定义字符其实很容易记忆,其中:

  • d 是 digit 的意思,代表数字。
  • s 是 space 的意思,代表空白。
  • w 是 word 的意思,代表单词。
  • d、s、w 的大写形式恰好匹配与之相反的字符。

有了上面的预定义字符后,接下来就可以创建更强大的正则表达式了。例如:

c\wt // 可以匹配cat、cbt、cct、cOt、c9t等一批字符串
\d\d\d-\d\d\d-\d\d\d\d // 匹配如 000-000-0000 形式的电话号码

在一些特殊情况下,例如,若只想匹配 a~f 的字母,或者匹配除 ab 之外的所有小写字母,或者匹配中文字符,上面这些预定义字符就无能为力了,此时就需要使用方括号表达式,方括号表达式有如表 4 所示的几种形式。

方括号表达式 说明
表示枚举 例如[abc]表示 a、b、c 其中任意一个字符;[gz]表示 g、z 其中任意一个字符
表示范围:- 例如[a-f]表示 a~f 范围内的任意字符;[\\u0041-\\u0056]表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如[a-cx-z],表示 ac、xz 范围内的任意字符
表示求否:^ 例如[^abc]表示非 a、b、c 的任意字符;[^a-f]表示不是 a~f 范围内的任意字符
表示“与”运算:&& 例如 [a-z&&[def]]是 a~z 和 [def] 的交集,表示 d、e f[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外 [ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符
表示“并”运算 并运算与前面的枚举类似。例如[a-d[m-p]]表示 [a-dm-p]

方括号表达式比前面的预定义字符灵活多了,几乎可以匹配任何字符。例如,若需要匹配所有的中文字符,就可以利用 [\u0041-\u0056] 形式——因为所有中文字符的 Unicode 值是连续的,只要找出所有中文字符中最小、最大的 Unicode 值,就可以利用上面形式来匹配所有的中文字符。

正则表达式还支持圆括号,用于将多个表达式组成一个子表达式,圆括号中可以使用或运算符|。例如,正则表达式“((public)|(protected)|(private))”用于匹配 Java 的三个访问控制符其中之一。

除此之外,Java 正则表达式还支持如表 5 所示的几个边界匹配符。

边界匹配符 说明
^ 行的开头
$ 行的结尾
\b 单词的边界
\B 非单词的边界
\A 输入的开头
\G 前一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符
\z 输入的结尾

前面例子中需要建立一个匹配 000-000-0000 形式的电话号码时,使用了 \d\d\d-\d\d\d-\d\d\d\d 正则表达式,这看起来比较烦琐。实际上,正则表达式还提供了数量标识符,正则表达式支持的数量标识符有如下几种模式。

  • Greedy(贪婪模式):数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。如果你发现表达式匹配的结果与预期的不符,很有可能是因为你以为表达式只会匹配前面几个字符,而实际上它是贪婪模式,所以会一直匹配下去。
  • Reluctant(勉强模式):用问号后缀(?)表示,它只会匹配最少的字符。也称为最小匹配模式。
  • Possessive(占有模式):用加号后缀(+)表示,目前只有 Java 支持占有模式,通常比较少用。

三种模式的数量表示符如表 6 所示。

贪婪模式 勉强模式 占用模式 说明
X? X?? X?+ X表达式出现零次或一次
X* X*? X*+ X表达式出现零次或多次
X+ X+? X++ X表达式出现一次或多次
X{n} X{n}? X{n}+ X表达式出现 n 次
X{n,} X{n,}? X{n,}+ X表达式最少出现 n 次
X{n,m} X{n,m}? X{n,m}+ X表达式最少出现 n 次,最多出现 m 次

关于贪婪模式和勉强模式的对比,看如下代码:

String str = "hello,java!";
// 贪婪模式的正则表达式
System.out.println(str.replaceFirst("\w" , "■")); //输出■,java!
// 勉强模式的正则表达式
System.out.println(str.replaceFirst("\w
?" , "■"")); //输出■hello, java!

当从“hello java!”字符串中查找匹配\\w*子串时,因为\w*使用了贪婪模式,数量表示符*会一直匹配下去,所以该字符串前面的所有单词字符都被它匹配到,直到遇到空格,所以替换后的效果是“■,Java!”;如果使用勉强模式,数量表示符*会尽量匹配最少字符,即匹配 0 个字符,所以替换后的结果是“■hello,java!”。

2. Pattern类和Matcher类的使用

java.util.regex 是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。它包括两个类:Pattern 和 Matcher。

Pattern 对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译为 Pattern 对象,然后再利用该 Pattern 对象创建对应的 Matcher 对象。执行匹配所涉及的状态保留在 Matcher 对象中,多个 Matcher 对象可共享同一个 Pattern 对象。

因此,典型的调用顺序如下:

// 将一个字符串编译成 Pattern 对象
Pattern p = Pattern.compile("a*b");
// 使用 Pattern 对象创建 Matcher 对象
Matcher m = p.matcher("aaaaab");
boolean b = m.matches(); // 返回 true

上面定义的 Pattern 对象可以多次重复使用。如果某个正则表达式仅需一次使用,则可直接使用 Pattern 类的静态 matches() 方法,此方法自动把指定字符串编译成匿名的 Pattern 对象,并执行匹配,如下所示。

boolean b = Pattern.matches ("a*b","aaaaab"); // 返回 true

上面语句等效于前面的三条语句。但采用这种语句每次都需要重新编译新的 Pattern 对象,不能重复利用已编译的 Pattern 对象,所以效率不高。Pattern 是不可变类,可供多个并发线程安全使用。

Matcher 类提供了几个常用方法,如表 1 所示。

名称 说明
find() 返回目标字符串中是否包含与 Pattern 匹配的子串
group() 返回上一次与 Pattern 匹配的子串
start() 返回上一次与 Pattern 匹配的子串在目标字符串中的开始位置
end() 返回上一次与 Pattern 匹配的子串在目标字符串中的结束位置加 1
lookingAt() 返回目标字符串前面部分与 Pattern 是否匹配
matches() 返回整个目标字符串与 Pattern 是否匹配
reset() 将现有的 Matcher 对象应用于一个新的字符序列。

在 Pattern、Matcher 类的介绍中经常会看到一个 CharSequence 接口,该接口代表一个字符序列,其中 CharBuffer、String、StringBuffer、StringBuilder 都是它的实现类。简单地说,CharSequence 代表一个各种表示形式的字符串。

通过 Matcher 类的 find() 和 group() 方法可以从目标字符串中依次取出特定子串(匹配正则表达式的子串),例如互联网的网络爬虫,它们可以自动从网页中识别出所有的电话号码。下面程序示范了如何从大段的字符串中找出电话号码。

public class FindGroup {   
public static void main(String[] args) {   
// 使用字符串模拟从网络上得到的网页源码     
String str = "我想找一套适合自己的JAVA教程,尽快联系我13500006666" + "交朋友,电话号码是13611125565" + "出售二手电脑,联系方式15899903312";    
// 创建一个Pattern对象,并用它建立一个Matcher对象    
// 该正则表达式只抓取13X和15X段的手机号    
// 实际要抓取哪些电话号码,只要修改正则表达式即可     
Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}").matcher(str);        // 将所有符合正则表达式的子串(电话号码)全部输出    
while (m.find()) {        
System.out.println(m.group());     
}  
}}

运行上面程序,看到如下运行结果:

13500006666
13611125565
15899903312

从上面运行结果可以看出,find() 方法依次查找字符串中与 Pattern 匹配的子串,一旦找到对应的子串,下次调用 find() 方法时将接着向下查找。

提示:通过程序运行结果可以看出,使用正则表达式可以提取网页上的电话号码,也可以提取邮件地址等信息。如果程序再进一步,可以从网页上提取超链接信息,再根据超链接打开其他网页,然后在其他网页上重复这个过程就可以实现简单的网络爬虫了。

find() 方法还可以传入一个 int 类型的参数,带 int 参数的 find() 方法将从该 int 索引处向下搜索。start() 和 end() 方法主要用于确定子串在目标字符串中的位置,如下程序所示。

public class StartEnd {   
public static void main(String[] args) {  
// 创建一个Pattern对象,并用它建立一个Matcher对象     
String regStr = "Java is very easy!";  
System.out.println("目标字符串是:" + regStr);    
Matcher m = Pattern.compile("\\w+").matcher(regStr); 
while (m.find()) {        
System.out.println(m.group() + "子串的起始位置:" + m.start() + ",其结束位置:" + m.end());   
}   
}}

上面程序使用 find()、group() 方法逐项取出目标字符串中与指定正则表达式匹配的子串,并使用 start()、end() 方法返回子串在目标字符串中的位置。运行上面程序,看到如下运行结果:

目标字符串是:Java is very easy!
Java子串的起始位置:0,其结束位置:4
is子串的起始位置:5,其结束位置:7
very子串的起始位置:8,其结束位置:12
easy子串的起始位置:13,其结束位置:17

matches() 和 lookingAt() 方法有点相似,只是 matches() 方法要求整个字符串和 Pattern 完全匹配时才返回 true,而 lookingAt() 只要字符串以 Pattern 开头就会返回 true。reset() 方法可将现有的 Matcher 对象应用于新的字符序列。看如下例子程序。

public class MatchesTest { 
public static void main(String[] args) {   
String[] mails = { "kongyeeku@163.com", "kongyeeku@gmail.com", "ligang@crazyit.org", "wawa@abc.xx" };   
String mailRegEx = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";    
Pattern mailPattern = Pattern.compile(mailRegEx);   
Matcher matcher = null;   
for (String mail : mails) {         
if (matcher == null) {         
matcher = mailPattern.matcher(mail);       
} else {           
matcher.reset(mail);   
}         
String result = mail + (matcher.matches() ? "是" : "不是") + "一个有效的邮件地址!";     
System.out.println(result);   
}  
}}

上面程序创建了一个邮件地址的 Pattern,接着用这个 Pattern 与多个邮件地址进行匹配。当程序中的 Matcher 为 null 时,程序调用 matcher() 方法来创建一个 Matcher 对象,一旦 Matcher 对象被创建,程序就调用 Matcher 的 reset() 方法将该 Matcher 应用于新的字符序列。

从某个角度来看,Matcher 的 matches()、lookingAt() 和 String 类的 equals() 有点相似。区别是 String 类的 equals() 都是与字符串进行比较,而 Matcher 的 matches() 和 lookingAt() 则是与正则表达式进行匹配。

事实上,String 类里也提供了 matches() 方法,该方法返回该字符串是否匹配指定的正则表达式。例如:

"kongyeeku@163.com".matches("\w{3,20}@\w+\.(com|org|cn|net|gov)"); // 返回 true

除此之外,还可以利用正则表达式对目标字符串进行分割、查找、替换等操作,看如下例子程序。

public class ReplaceTest {  
public static void main(String[] args) {  
String[] msgs = { "Java has regular expressions in 1.4", "regular expressions now expressing in Java",  "Java represses oracular expressions" };    
Pattern p = Pattern.compile("re\\w*");     
Matcher matcher = null;   
for (int i = 0; i < msgs.length; i++) {       
if (matcher == null) {           
matcher = p.matcher(msgs[i]);        
} else {           
matcher.reset(msgs[i]);      
}       
System.out.println(matcher.replaceAll("哈哈:)"));     
}    
}}

上面程序使用了 Matcher 类提供的 replaceAll() 把字符串中所有与正则表达式匹配的子串替换成“哈哈:)”,实际上,Matcher 类还提供了一个 replaceFirst(),该方法只替换第一个匹配的子串。运行上面程序,会看到字符串中所有以“re”开头的单词都会被替换成“哈哈:)”。

实际上,String 类中也提供了 replaceAll()、replaceFirst()、split() 等方法。下面的例子程序直接使用 String 类提供的正则表达式功能来进行替换和分割。

public class StringReg {   
public static void main(String[] args) {   
String[] msgs = { "Java has regular expressions in 1.4", "regular expressions now expressing in Java",  "Java represses oracular expressions" };    
for (String msg : msgs) {    
System.out.println(msg.replaceFirst("re\\w*", "哈哈:)"));        
System.out.println(Arrays.toString(msg.split(" ")));  
}    
}
}

上面程序只使用 String 类的 replaceFirst() 和 split() 方法对目标字符串进行了一次替换和分割。运行上面程序,会看到如下所示的输出结果。

Java has 哈哈:) expressions in 1.4
[Java, has, regular, expressions, in, 1.4]
哈哈:) expressions now expressing in Java
[regular, expressions, now, expressing, in, Java]
Java 哈哈:) oracular expressions
[Java, represses, oracular, expressions]

正则表达式是一个功能非常灵活的文本处理工具,增加了正则表达式支持后的 Java,可以不再使用 StringTokenizer 类(也是一个处理字符串的工具,但功能远不如正则表达式强大)即可进行复杂的字符串处理。

十一、数字和日期

Math 类中包含 E 和 PI 两个静态常量,正如它们名字所暗示的,它们的值分别等于 e(自然对数)和 π(圆周率)。

1.常量

调用 Math 类的 E 和 PI 两个常量,并将结果输出。代码如下:

System.out.println("E 常量的值:" + Math.E);System.out.println("PI 常量的值:" + Math.PI);

执行上述代码,输出结果如下:

E 常量的值:2.718281828459045
PI 常量的值:3.141592653589793

2.求最大值、最小值和绝对值

在程序中常见的就是求最大值、最小值和绝对值问题,如果使用 Math 类提供的方法可以很容易实现。这些方法的说明如表 1 所示。

方法 说明
static int abs(int a) 返回 a 的绝对值
static long abs(long a) 返回 a 的绝对值
static float abs(float a) 返回 a 的绝对值
static double abs(double a) 返回 a 的绝对值
static int max(int x,int y) 返回 x 和 y 中的最大值
static double max(double x,double y) 返回 x 和 y 中的最大值
static long max(long x,long y) 返回 x 和 y 中的最大值
static float max(float x,float y) 返回 x 和 y 中的最大值
static int min(int x,int y) 返回 x 和 y 中的最小值
static long min(long x,long y) 返回 x 和 y 中的最小值
static double min(double x,double y) 返回 x 和 y 中的最小值
static float min(float x,float y) 返回 x 和 y 中的最小值

求 10 和 20 的较大值、15.6 和 15 的较小值、-12 的绝对值,代码如下:

public class Test02 {  
public static void main(String[] args) {    
System.out.println("10 和 20 的较大值:" + Math.max(10, 20));     
System.out.println("15.6 和 15 的较小值:" + Math.min(15.6, 15));     
System.out.println("-12 的绝对值:" + Math.abs(-12));   
}}

该程序的运行结果如下:

10和20的较大值:20
15.6和15的较小值:15.0
-12的绝对值:12

3.求整运算

Math 类的求整方法有很多,详细说明如表 2 所示。

方法 说明
static double ceil(double a) 返回大于或等于 a 的最小整数
static double floor(double a) 返回小于或等于 a 的最大整数
static double rint(double a) 返回最接近 a 的整数值,如果有两个同样接近的整数,则结果取偶数
static int round(float a) 将参数加上 1/2 后返回与参数最近的整数
static long round(double a) 将参数加上 1/2 后返回与参数最近的整数,然后强制转换为长整型

下面的实例演示了 Math 类中取整函数方法的应用:

import java.util.Scanner;public class Test03 {   
public static void main(String[] args) {      
Scanner input = new Scanner(System.in);     
System.outprintln("请输入一个数字:"); 
double num = input.nextDouble();        
System.out.println("大于或等于 "+ num +" 的最小整数:" + Math.ceil(num));      
System.out.println("小于或等于 "+ num +" 的最大整数:" + Math.floor(num));      
System.out.println("将 "+ num +" 加上 0.5 之后最接近的整数:" + Math.round(num));    
System.out.println("最接近 "+num+" 的整数:" + Math.rint(num));   
}
}

执行结果如下:

请输入一个数字:
99.01
大于或等于 99.01 的最小整数:100.0
小于或等于 99.01 的最大整数:99.0
将 99.01 加上 0.5 之后最接近的整数:100
最接近 99.01 的整数:99.0

4.三角函数运算

Math 类中包含的三角函数方法及其说明如表 3 所示。

方法 说明
static double sin(double a) 返回角的三角正弦值,参数以孤度为单位
static double cos(double a) 返回角的三角余弦值,参数以孤度为单位
static double asin(double a) 返回一个值的反正弦值,参数域在 [-1,1],值域在 [-PI/2,PI/2]
static double acos(double a) 返回一个值的反余弦值,参数域在 [-1,1],值域在 [0.0,PI]
static double tan(double a) 返回角的三角正切值,参数以弧度为单位
static double atan(double a) 返回一个值的反正切值,值域在 [-PI/2,PI/2]
static double toDegrees(double angrad) 将用孤度表示的角转换为近似相等的用角度表示的角
staticdouble toRadians(double angdeg) 将用角度表示的角转换为近似相等的用弧度表示的角

在表 3 中,每个方法的参数和返回值都是 double 类型,参数以弧度代替角度来实现,其中 1 度等于 π/180 弧度,因此平角就是 π 弧度。

计算 90 度的正弦值、0 度的余弦值、1 的反正切值、120 度的弧度值,代码如下:

public class Test04 {   
public static void main(String[] args) {  
System.out.println{"90 度的正弦值:" + Math.sin(Math.PI/2));    
System.out.println("0 度的余弦值:" + Math.cos(0));     
System.out.println("1 的反正切值:" + Math.atan(l));    
System.out.println("120 度的弧度值:" + Math.toRadians(120.0));  
}
}

在上述代码中,因为 Math.sin() 中的参数的单位是弧度,而 90 度表示的是角度,因此需要将 90 度转换为弧度,即 Math.PI/180*90,故转换后的弧度为 Math.PI/2,然后调用 Math 类中的 sin() 方法计算其正弦值。

该程序的运行结果如下:

90 度的正弦值:1.0
0 的余弦值:1.0
1 的反正切值:0.7853981633974483
120 度的弧度值:2.0943951023931953

5.指数运算

指数的运算包括求方根、取对数及其求 n 次方的运算。在 Math 类中定义的指数运算方法及其说明如表 4 所示。

方法 说明
static double exp(double a) 返回 e 的 a 次幂
static double pow(double a,double b) 返回以 a 为底数,以 b 为指数的幂值
static double sqrt(double a) 返回 a 的平方根
static double cbrt(double a) 返回 a 的立方根
static double log(double a) 返回 a 的自然对数,即 lna 的值
static double log10(double a) 返回以 10 为底 a 的对数

使用 Math 类中的方法实现指数的运算,main() 方法中的代码如下:

public class Test05 {  
public static void main(String[] args) {  
System.out.println("4 的立方值:" + Math.pow(4, 3));  
System.out.println("16 的平方根:" + Math.sqrt(16));   
System.out.println("10 为底 2 的对数:" + Math.log1O(2)); 
}
}

该程序的运行结果如下:

4 的立方值:64.0
16 的平方根:4.0
10 为底 2 的对数:0.3010299956639812

6.随机数

Java 中要生成一个指定范围之内的随机数字有两种方法:一种是调用 Math 类的 random() 方法,一种是使用 Random 类。

Random 类提供了丰富的随机数生成方法,可以产生 boolean、int、long、float、byte 数组以及 double 类型的随机数,这是它与 random() 方法最大的不同之处。random() 方法只能产生 double 类型的 0~1 的随机数。

Random 类位于 java.util 包中,该类常用的有如下两个构造方法。

  • Random():该构造方法使用一个和当前系统时间对应的数字作为种子数,然后使用这个种子数构造 Random 对象。
  • Random(long seed):使用单个 long 类型的参数创建一个新的随机数生成器。

Random 类提供的所有方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的概率是均等的,在表 1 中列出了 Random 类中常用的方法。

方法 说明
boolean nextBoolean() 生成一个随机的 boolean 值,生成 true 和 false 的值概率相等
double nextDouble() 生成一个随机的 double 值,数值介于 [0,1.0),含 0 而不包含 1.0
int nextlnt() 生成一个随机的 int 值,该值介于 int 的区间,也就是 -231~231-1。如果 需要生成指定区间的 int 值,则需要进行一定的数学变换
int nextlnt(int n) 生成一个随机的 int 值,该值介于 [0,n),包含 0 而不包含 n。如果想生成 指定区间的 int 值,也需要进行一定的数学变换
void setSeed(long seed) 重新设置 Random 对象中的种子数。设置完种子数以后的 Random 对象 和相同种子数使用 new 关键字创建出的 Random 对象相同
long nextLong() 返回一个随机长整型数字
boolean nextBoolean() 返回一个随机布尔型值
float nextFloat() 返回一个随机浮点型数字
double nextDouble() 返回一个随机双精度值

7.数字格式化

1.DecimalFormat()

DecimalFormat 是 NumberFormat 的一个子类,用于格式化十进制数字。DecimalFormat 类包含一个模式和一组符号,常用符号的说明如表 1 所示。

符号 说明
0 显示数字,如果位数不够则补 0
# 显示数字,如果位数不够不发生变化
. 小数分隔符
- 减号
, 组分隔符
E 分隔科学记数法中的尾数和小数
% 前缀或后缀,乘以 100 后作为百分比显示
? 乘以 1000 后作为千进制货币符显示。用货币符号代替。如果双写,用国际货币符号代替; 如果出现在一个模式中,用货币十进制分隔符代替十进制分隔符

下面编写一个 Java 程序,演示如何使用 DecimalFormat 类将数字转换成各种格式,实现代码如下。

import java.text.DecimalFormat;
import java.util.Scanner;

public class Test08 {
    public static void main(String[] args) {
        // 实例化DecimalFormat类的对象,并指定格式
        DecimalFormat df1 = new DecimalFormat("0.0");
        DecimalFormat df2 = new DecimalFormat("#.#");
        DecimalFormat df3 = new DecimalFormat("000.000");
        DecimalFormat df4 = new DecimalFormat("###.###");
        Scanner scan = new Scanner(System.in);
        System.out.print("请输入一个float类型的数字:");
        float f = scan.nextFloat();
        // 对输入的数字应用格式,并输出结果
        System.out.println("0.0 格式:" + df1.format(f));
        System.out.println("#.# 格式:" + df2.format(f));
        System.out.println("000.000 格式:" + df3.format(f));
        System.out.println("###.### 格式:" + df4.format(f));
    }
}

执行上述代码,输出结果如下所示:

请输入一个float类型的数字:5487.45697
0.0 格式:5487.5
#.# 格式:5487.5
000.000 格式:5487.457
###.### 格式:5487.457
请输入一个float类型的数字:5.0
0.0 格式:5.0
#.# 格式:5
000.000 格式:005.000
###.### 格式:5

8.大数字运算

1.BigInteger类

  1. BigInteger(String val)

  2. 方法名称 说明
    add(BigInteger val) 做加法运算
    subtract(BigInteger val) 做减法运算
    multiply(BigInteger val) 做乘法运算
    divide(BigInteger val) 做除法运算
    remainder(BigInteger val) 做取余数运算
    divideAndRemainder(BigInteger val) 做除法运算,返回数组的第一个值为商,第二个值为余数
    pow(int exponent) 做参数的 exponent 次方运算
    negate() 取相反数
    shiftLeft(int n) 将数字左移 n 位,如果 n 为负数,则做右移操作
    shiftRight(int n) 将数字右移 n 位,如果 n 为负数,则做左移操作
    and(BigInteger val) 做与运算
    or(BigInteger val) 做或运算
    compareTo(BigInteger val) 做数字的比较运算
    equals(Object obj) 当参数 obj 是 Biglnteger 类型的数字并且数值相等时返回 true, 其他返回 false
    min(BigInteger val) 返回较小的数值
    max(BigInteger val) 返回较大的数值

2.BigDecimal类

BigDecimal 常用的构造方法如下。

  • BigDecimal(double val):实例化时将双精度型转换为 BigDecimal 类型。

  • BigDecimal(String val):实例化时将字符串形式转换为 BigDecimal 类型。

    1. BigDecimal add(BigDecimal augend) // 加法操作

    2. BigDecimal subtract(BigDecimal subtrahend) // 减法操作

    3. BigDecimal multiply(BigDecimal multiplieand) // 乘法操作

    4. BigDecimal divide(BigDecimal divisor,int scale,int roundingMode ) // 除法操作

    5. roundingMode 参数支持的处理模式:

    6. 模式名称 说明
      BigDecimal.ROUND_UP 商的最后一位如果大于 0,则向前进位,正负数都如此
      BigDecimal.ROUND_DOWN 商的最后一位无论是什么数字都省略
      BigDecimal.ROUND_CEILING 商如果是正数,按照 ROUND_UP 模式处理;如果是负数,按照 ROUND_DOWN 模式处理
      BigDecimal.ROUND_FLOOR 与 ROUND_CELING 模式相反,商如果是正数,按照 ROUND_DOWN 模式处理; 如果是负数,按照 ROUND_UP 模式处理
      BigDecimal.ROUND_HALF_ DOWN 对商进行五舍六入操作。如果商最后一位小于等于 5,则做舍弃操作,否则对最后 一位进行进位操作
      BigDecimal.ROUND_HALF_UP 对商进行四舍五入操作。如果商最后一位小于 5,则做舍弃操作,否则对最后一位 进行进位操作
      BigDecimal.ROUND_HALF_EVEN 如果商的倒数第二位是奇数,则按照 ROUND_HALF_UP 处理;如果是偶数,则按 照 ROUND_HALF_DOWN 处理

9.日期处理

1.Date类

  • Date 类表示系统特定的时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。

  • Date 类有如下两个构造方法。

    • Date():此种形式表示分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒),使用该构造方法创建的对象可以获取本地的当前时间。
    • Date(long date):此种形式表示从 GMT 时间(格林尼治时间)1970 年 1 月 1 日 0 时 0 分 0 秒开始经过参数 date 指定的毫秒数。
  • 方法 描述
    boolean after(Date when) 判断此日期是否在指定日期之后
    boolean before(Date when) 判断此日期是否在指定日期之前
    int compareTo(Date anotherDate) 比较两个日期的顺序
    boolean equals(Object obj) 比较两个日期的相等性
    long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来,此 Date 对象表示的毫秒数
    String toString() 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy。 其中 dow 是一周中的某一天(Sun、Mon、Tue、Wed、Thu、Fri 及 Sat)

2.Calendar类

  • 创建 Calendar 对象不能使用 new 关键字,因为 Calendar 类是一个抽象类,但是它提供了一个 getInstance() 方法来获得 Calendar类的对象。getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化。

  • Calendar c = Calendar.getInstance();
    
  • 方法 描述
    void add(int field, int amount) 根据日历的规则,为给定的日历字段 field 添加或减去指定的时间量 amount
    boolean after(Object when) 判断此 Calendar 表示的时间是否在指定时间 when 之后,并返回判断结果
    boolean before(Object when) 判断此 Calendar 表示的时间是否在指定时间 when 之前,并返回判断结果
    void clear() 清空 Calendar 中的日期时间值
    int compareTo(Calendar anotherCalendar) 比较两个 Calendar 对象表示的时间值(从格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒至现在的毫秒偏移量),大则返回 1,小则返回 -1,相等返回 0
    int get(int field) 返回指定日历字段的值
    int getActualMaximum(int field) 返回指定日历字段可能拥有的最大值
    int getActualMinimum(int field) 返回指定日历字段可能拥有的最小值
    int getFirstDayOfWeek() 获取一星期的第一天。根据不同的国家地区,返回不同的值
    static Calendar getInstance() 使用默认时区和语言坏境获得一个日历
    static Calendar getInstance(TimeZone zone) 使用指定时区和默认语言环境获得一个日历
    static Calendar getInstance(TimeZone zone, Locale aLocale) 使用指定时区和语言环境获得一个日历
    Date getTime() 返回一个表示此 Calendar 时间值(从格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒至现在的毫秒偏移量)的 Date 对象
    long getTimeInMillis() 返回此 Calendar 的时间值,以毫秒为单位
    void set(int field, int value) 为指定的日历字段设置给定值
    void set(int year, int month, int date) 设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值
    void set(int year, int month, int date, int hourOfDay, int minute, int second) 设置字段 YEAR、MONTH、DAY_OF_MONTH、HOUR、 MINUTE 和 SECOND 的值
    void setFirstDayOfWeek(int value) 设置一星期的第一天是哪一天
    void setTimeInMillis(long millis) 用给定的 long 值设置此 Calendar 的当前时间值

Calendar 对象可以调用 set() 方法将日历翻到任何一个时间,当参数 year 取负数时表示公元前。Calendar 对象调用 get() 方法可以获取有关年、月、日等时间信息,参数 field 的有效值由 Calendar 静态常量指定。

Calendar 类中定义了许多常量,分别表示不同的意义。

  • Calendar.YEAR:年份。
  • Calendar.MONTH:月份。
  • Calendar.DATE:日期。
  • Calendar.DAY_OF_MONTH:日期,和上面的字段意义完全相同。
  • Calendar.HOUR:12小时制的小时。
  • Calendar.HOUR_OF_DAY:24 小时制的小时。
  • Calendar.MINUTE:分钟。
  • Calendar.SECOND:秒。
  • Calendar.DAY_OF_WEEK:星期几。

例如:int month = Calendar.getInstance().get(Calendar.MONTH);

3.DateFormat 类

在创建 DateFormat 对象时不能使用 new 关键字,而应该使用 DateFormat 类中的静态方法 getDateInstance(),示例代码如下:

DateFormat df = DateFormat.getDatelnstance();
方法 描述
String format(Date date) 将 Date 格式化日期/时间字符串
Calendar getCalendar() 获取与此日期/时间格式相关联的日历
static DateFormat getDateInstance() 获取具有默认格式化风格和默认语言环境的日期格式
static DateFormat getDateInstance(int style) 获取具有指定格式化风格和默认语言环境的日期格式
static DateFormat getDateInstance(int style, Locale locale) 获取具有指定格式化风格和指定语言环境的日期格式
static DateFormat getDateTimeInstance() 获取具有默认格式化风格和默认语言环境的日期/时间 格式
static DateFormat getDateTimeInstance(int dateStyle,int timeStyle) 获取具有指定日期/时间格式化风格和默认语言环境的 日期/时间格式
static DateFormat getDateTimeInstance(int dateStyle,int timeStyle,Locale locale) 获取具有指定日期/时间格式化风格和指定语言环境的 日期/时间格式
static DateFormat getTimeInstance() 获取具有默认格式化风格和默认语言环境的时间格式
static DateFormat getTimeInstance(int style) 获取具有指定格式化风格和默认语言环境的时间格式
static DateFormat getTimeInstance(int style, Locale locale) 获取具有指定格式化风格和指定语言环境的时间格式
void setCalendar(Calendar newCalendar) 为此格式设置日历
Date parse(String source) 将给定的字符串解析成日期/时间

格式化样式主要通过 DateFormat 常量设置。将不同的常量传入到表 1 所示的方法中,以控制结果的长度。DateFormat 类的常量如下。

  • SHORT:完全为数字,如 12.5.10 或 5:30pm。
  • MEDIUM:较长,如 May 10,2016。
  • LONG:更长,如 May 12,2016 或 11:15:32am。
  • FULL:是完全指定,如 Tuesday、May 10、2012 AD 或 11:l5:42am CST。

4.SimpleDateFormat 类

  • 如果使用 DateFormat 类格式化日期/时间并不能满足要求,那么就需要使用 DateFormat 类的子类——SimpleDateFormat

  • SimpleDateFormat 类主要有如下 3 种构造方法。

    • SimpleDateFormat():用默认的格式和默认的语言环境构造 SimpleDateFormat。
    • SimpleDateFormat(String pattern):用指定的格式和默认的语言环境构造 SimpleDateF ormat。
    • SimpleDateFormat(String pattern,Locale locale):用指定的格式和指定的语言环境构造 SimpleDateF ormat。
  • 字母 含义 示例
    y 年份。一般用 yy 表示两位年份,yyyy 表示 4 位年份 使用 yy 表示的年扮,如 11; 使用 yyyy 表示的年份,如 2011
    M 月份。一般用 MM 表示月份,如果使用 MMM,则会 根据语言环境显示不同语言的月份 使用 MM 表示的月份,如 05; 使用 MMM 表示月份,在 Locale.CHINA 语言环境下,如“十月”;在 Locale.US 语言环境下,如 Oct
    d 月份中的天数。一般用 dd 表示天数 使用 dd 表示的天数,如 10
    D 年份中的天数。表示当天是当年的第几天, 用 D 表示 使用 D 表示的年份中的天数,如 295
    E 星期几。用 E 表示,会根据语言环境的不同, 显示不 同语言的星期几 使用 E 表示星期几,在 Locale.CHINA 语 言环境下,如“星期四”;在 Locale.US 语 言环境下,如 Thu
    H 一天中的小时数(0~23)。一般用 HH 表示小时数 使用 HH 表示的小时数,如 18
    h 一天中的小时数(1~12)。一般使用 hh 表示小时数 使用 hh 表示的小时数,如 10 (注意 10 有 可能是 10 点,也可能是 22 点)
    m 分钟数。一般使用 mm 表示分钟数 使用 mm 表示的分钟数,如 29
    s 秒数。一般使用 ss 表示秒数 使用 ss 表示的秒数,如 38
    S 毫秒数。一般使用 SSS 表示毫秒数 使用 SSS 表示的毫秒数,如 156

接下来看java基础学习(四)

java基础学习(三)

原文:https://www.cnblogs.com/namusangga/p/14613653.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!