Java常见API(二)
BigInteger
在Java中,BigInteger
是一个用于任意精度的有符号整数的类。当你需要表示和操作超过 long
类型范围的整数时,BigInteger
就非常有用。它提供了各种算术运算,如加、减、乘、除、模运算等,以及位运算和比较操作。
使用方法:
- 创建 BigInteger 对象:
BigInteger bigNum1 = new BigInteger("12345678901234567890");
BigInteger bigNum2 = BigInteger.valueOf(1234567890L);
- 进行算术运算:
BigInteger sum = bigNum1.add(bigNum2);
BigInteger diff = bigNum1.subtract(bigNum2);
BigInteger prod = bigNum1.multiply(bigNum2);
BigInteger quot = bigNum1.divide(bigNum2);
BigInteger rem = bigNum1.mod(bigNum2);
- 比较:
int comparison = bigNum1.compareTo(bigNum2);
if (comparison > 0) {
System.out.println("bigNum1 is greater");
} else if (comparison < 0) {
System.out.println("bigNum2 is greater");
} else {
System.out.println("They are equal");
}
注意事项:
- 性能:
BigInteger
的运算通常比基本数据类型(如int
、long
)的运算慢得多,因为它需要处理动态大小的数字,并且使用对象而非基本数据类型会增加内存开销。 - 精度:由于
BigInteger
支持任意精度的整数,因此不存在溢出的问题。 - 不可变性:
BigInteger
的实例是不可变的,这意味着每次进行算术运算时都会返回一个新的BigInteger
对象。
常用和对竞赛有帮助的方法:
- 模幂运算:使用
modPow
方法可以快速计算大整数的模幂运算,这在许多加密算法(如RSA)中非常有用。 - 快速乘法和快速幂:虽然
BigInteger
类内部已经优化了这些操作,但了解这些算法的原理可以帮助你更好地理解其性能特点。 - 位运算:
BigInteger
也提供了位运算方法,如and
、or
、xor
、shiftLeft
、shiftRight
等,这些在解决某些问题时可能很有用。 - 比较和排序:使用
compareTo
方法可以对BigInteger
对象进行排序或比较。
在编程竞赛中,BigInteger
通常用于解决涉及大整数运算的问题,如高精度计算、数论问题等。了解并熟练使用 BigInteger
可以帮助你解决这些问题。
BigDecimal
在Java中,BigDecimal是一个用于表示任意精度的不可变的、任意精度的有符号十进制数的类。它主要用于需要进行精确计算的情况,特别是金融计算和科学计算等领域,以避免浮点数计算带来的精度损失。
BigDecimal的用途:
- 金融计算:金融领域对数值的精度要求非常高,BigDecimal提供了高精度的数值运算,可以避免浮点数计算带来的精度损失。
- 科学计算:在科学计算中,往往需要处理大量的高精度数据,BigDecimal可以满足这种需求。
- 精确的小数运算:当需要精确控制小数位数和舍入方式时,BigDecimal是一个很好的选择。
BigDecimal的使用:
- 构造方法:
BigDecimal(double val)
:使用double类型的值创建BigDecimal对象。但通常不推荐使用此方法,因为double类型的精度问题可能会导致结果不准确。BigDecimal(String val)
:使用字符串表示的数值创建BigDecimal对象。这是推荐的方式,因为字符串可以精确地表示数值。BigDecimal(int val)
:使用int类型的值创建BigDecimal对象。
- 算术运算:
add(BigDecimal augend)
:加法运算。subtract(BigDecimal subtrahend)
:减法运算。multiply(BigDecimal multiplicand)
:乘法运算。divide(BigDecimal divisor, int scale, int roundingMode)
:除法运算,其中scale表示小数点后的位数,roundingMode表示舍入模式。
- 其他常用方法:
setScale(int newScale, int roundingMode)
:设置小数点后的位数和舍入模式。compareTo(BigDecimal val)
:比较两个BigDecimal对象的大小。toString()
:将BigDecimal对象转换为字符串。doubleValue()
、floatValue()
、longValue()
、intValue()
:将BigDecimal对象转换为对应的基本数据类型。
注意事项:
- 精度问题:尽量避免使用double类型的值来创建BigDecimal对象,因为double类型本身存在精度问题。最好使用字符串作为构造函数的参数来表示数值。
- 不可变性:BigDecimal对象是不可变的,每次进行运算都会返回一个新的BigDecimal对象。
- 除法运算:在进行除法运算时,需要特别注意除数为0的情况,以及选择合适的舍入模式。
常用和对打竞赛有帮助的方法:
- 比较方法:
compareTo()
方法用于比较两个BigDecimal对象的大小,这在排序和查找等算法中非常有用。 - 四舍五入:
setScale()
方法用于设置小数点后的位数和舍入模式,这在需要精确控制小数位数和舍入方式的场景中非常有用。 - 字符串转换:
toString()
方法可以将BigDecimal对象转换为字符串,这在需要将计算结果输出到控制台或保存到文件时非常有用。
在编程竞赛中,BigDecimal常用于解决涉及高精度计算的问题,如计算器的实现、财务计算等。熟练掌握BigDecimal的使用方法和注意事项,可以帮助你更准确地解决这些问题。
正则表达式
- 注意事项:从从左往右一个一个字符的匹配的
- ()这个表示分组
在Java中,正则表达式(Regular Expression,简称regex或regexp)是一种强大的文本处理工具,它使用一种特定格式的字符串来描述、匹配和查找文本模式。正则表达式在Java中广泛应用于各种文本处理任务,如验证用户输入、搜索和替换文本中的特定模式等。
正则表达式的作用:
- 验证:用于验证用户输入是否符合特定格式,如电子邮件地址、电话号码等。
- 搜索:在文本中查找符合特定模式的字符串。
- 替换:将文本中符合特定模式的字符串替换为其他字符串。
如何使用正则表达式:
在Java中,java.util.regex
包提供了正则表达式的支持。主要的类有 Pattern
和 Matcher
。
- 创建Pattern对象:使用
Pattern.compile()
方法将正则表达式编译为Pattern
对象。
Pattern pattern = Pattern.compile("\\d+"); // 匹配一个或多个数字
- 创建Matcher对象:使用
Pattern
对象的matcher()
方法创建Matcher
对象,用于在目标字符串上进行匹配操作。
Matcher matcher = pattern.matcher("abc123def456");
- 执行匹配操作:使用
Matcher
对象的各种方法执行匹配操作,如find()
,matches()
,replaceAll()
,replaceFirst()
等。
if (matcher.find()) {
System.out.println("Found match: " + matcher.group());
}
注意事项:
- 转义字符:在正则表达式中,一些特殊字符(如
.
,*
,?
,+
,^
,$
,[
,]
,{
,}
,(
,)
,|
,\
)需要转义才能表示其字面意义。可以使用反斜杠\
进行转义。 - 性能问题:复杂的正则表达式可能导致性能问题,特别是在处理大量文本时。尽量保持正则表达式的简洁和高效。
- 可读性:复杂的正则表达式可能难以理解和维护。为了提高可读性,可以使用命名捕获组、注释等特性。
常用和对打竞赛有帮助的方法:
- 匹配方法:
matches()
:整个区域与模式匹配。find()
:查找下一个匹配项。lookingAt()
:从输入序列的起始位置开始尝试匹配模式。
- 替换方法:
replaceAll()
:替换所有匹配项。replaceFirst()
:替换第一个匹配项。
-
分组与捕获:使用括号
()
创建捕获组,可以通过Matcher
的group()
方法获取捕获的内容。 -
边界匹配:
^
:匹配输入字符串的开始位置。$
:匹配输入字符串的结束位置。\b
:匹配一个单词边界。
- 预定义字符类:
.
:匹配任何单个字符(除了换行符)。\d
:匹配一个数字字符。\D
:匹配一个非数字字符。\s
:匹配任何空白字符。\S
:匹配任何非空白字符。\w
:匹配任何单词字符(等价于[a-zA-Z_0-9]
)。\W
:匹配任何非单词字符。
在编程竞赛中,正则表达式常用于文本解析、模式识别等任务。熟练掌握正则表达式的基本语法和常用方法,能够帮助你快速解决相关问题。
利用正则表达式爬取内容
package com.mohuanan.pazhong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Demo01 {
public static void main(String[] args) {
//爬取本地的内容
//内容
String str = "莫华南1和莫华棋和莫华南和莫华2和莫华南3";
//获取正则表达式的对象
Pattern p = Pattern.compile("莫华南\\d{0,1}");
//获取文本匹配器的对象
//拿着m去读str里面符合p规则的子串
Matcher m = p.matcher(str);
//find 会逐个找符合的子串 找到一个就返回true
while(m.find()){
//根据find(下标,最后+1)获取 正确的内容
//再根据 subString
String group = m.group();
System.out.println(group);
}
}
}
package com.mohuanan.pazhong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Demo02 {
public static void main(String[] args) {
String s = "17362205666,13557944666";
//电话号码的正则表达式
String numberRegex = "1[3-8]\\d{9}";
//邮箱的正则表达式
//(): 分组
String mailRegex = "\\w+@[\\w&&[^_]{2,6}(\\.[a-zA-Z]{2,3}){1,2}]";
//座机的正则表达式
//-?一次或者一次都没有
String planeRegex = "0\\d{2,3}-?[1-9]\\d{4,9}";
//热线电话的正则表达式
String hoteNumber = "400-?[1-9]\\d{2}-?[1-9]\\d{3}";
String[] regex = {
"1[3-8]\\d{9}",
"\\w+@[\\w&&[^_]{2,6}(\\.[a-zA-Z]{2,3}){1,2}]",
"0\\d{2,3}-?[1-9]\\d{4,9}",
"400-?[1-9]\\d{2}-?[1-9]\\d{3}"
};
Pattern p;
for (int i = 0; i < regex.length; i++) {
//获取正则表达式的对象
p = Pattern.compile(regex[i]);
//获取文本匹配器的对象
Matcher m = p.matcher(s);
while(m.find()){
String str = m.group();
System.out.println(str);
}
}
}
}
在Java中,String
类关于正则表达式的常用方法除了matches()
之外,还有以下几个:
split(String regex)
:
该方法使用给定的正则表达式作为分隔符将字符串拆分为子字符串数组。
String str = "one,two,three,four";
String[] parts = str.split(",");
// parts 现在包含 ["one", "two", "three", "four"]
replaceFirst(String regex, String replacement)
:
该方法使用给定的正则表达式来查找第一个匹配项,并使用给定的替换字符串替换它。
String str = "apple orange apple";
String newStr = str.replaceFirst("apple", "banana");
// newStr 现在包含 "banana orange apple"
replaceAll(String regex, String replacement)
:
该方法使用给定的正则表达式来查找所有匹配项,并使用给定的替换字符串替换它们。
String str = "apple orange apple";
String newStr = str.replaceAll("apple", "banana");
// newStr 现在包含 "banana orange banana"
contains(CharSequence s)
:
虽然这个方法不是基于正则表达式的,但它可以用来检查字符串是否包含另一个子字符串。如果要在正则表达式匹配时使用类似的功能,可以使用Pattern
和Matcher
类。
String str = "Hello, world!";
boolean contains = str.contains("world");
// contains 为 true
除了String
类中的方法,Java还提供了Pattern
和Matcher
类来进行更复杂的正则表达式操作。Pattern
类用于编译正则表达式,并创建一个Pattern
对象,然后可以使用Matcher
类来执行匹配操作。
使用Pattern
和Matcher
的常见方法包括:
Pattern.compile(String regex)
: 编译正则表达式并返回一个Pattern
对象。Pattern.matcher(CharSequence input)
: 创建一个匹配器,用于匹配输入序列与此模式。Matcher.find()
: 尝试查找与该模式匹配的输入序列的下一个子序列。Matcher.group()
: 返回由以前匹配操作所匹配的输入子序列。Matcher.start()
,Matcher.end()
: 返回最近一次匹配操作的开始和结束索引。
例子:
Pattern pattern = Pattern.compile("\\d+"); // 匹配一个或多个数字
Matcher matcher = pattern.matcher("There are 123 apples and 456 oranges.");
while (matcher.find()) {
System.out.println("Found number: " + matcher.group());
}
// 输出:
// Found number: 123
// Found number: 456
使用Pattern
和Matcher
类可以执行更复杂的正则表达式匹配和替换操作,并且提供更多的控制和灵活性。
package com.mohuanan.pazhong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Demo03 {
public static void main(String[] args) {
String s = "6666";
//1. 带有选择性的爬取
//(?i) 表示java补区分大小写
//? 理解为前面的数据Java
//= 表示在java后面要跟随的数据
//?= 但是在获取的时侯,只输出前面的Java
String refex1 = "((?i)java)(?=8|11|17)";
//?: 表示在获取的时候,把java后面的8或者11或者17也给输出
String regex2 = "((?i)java)(?:8|11|17)";
//?! 表示爬取除了Java8或者java11或者java17的java文本
String regex3 = "((?i)java)(?!8|11|17)";
//获取Pattern(正则表达式)对象
Pattern p = Pattern.compile(refex1);
//获取文本匹配器的对象
Matcher m = p.matcher(s);
//遍历获取
while(m.find()){
String group = m.group();
System.out.println(group);
}
//2. 贪婪爬取和非贪婪爬取
//在Java中默认的是贪婪爬取
//在+ 或者* 的后面加上一个? 就表示非贪婪爬取
//这里只有b是加的表示 b尽可能多的出现
String regex4 = "ab+";
String regex5 = "ab+?";
String s2 = "123";
String string = s2.replaceAll(regex4, "vs");
String[] arr = s2.split("[1-9]\\d+");
//split得到的是一个字符串数组
//遍历输出字符串数组里面的内容
for (int i = 0; i < arr.length; i++) {
String t = arr[i];
System.out.println(t);
}
}
}
package com.mohuanan.pazhong;
public class Demo05 {
public static void main(String[] args) {
// \\表示组号 \\1这里是拿出第一组的内容再用一次
String regex1 = "(.).+\\1";
System.out.println("a123a".matches(regex1));
System.out.println("a123b".matches(regex1));
System.out.println("-------------");
String regex2 = "(.+).+\\1";
System.out.println("abc123abc".matches(regex2));
System.out.println("abc123abd".matches(regex2));
System.out.println("---------------");
//开始部分的每一个字符需要保证一致
//(.)把首字母看作是一组
// \\2* 前面的改组数据重复出现0次或者多次;注意是重复 ,前面(.)已经出现了一次了
//第一个左括号是第一组 以此类推
String regex3 = "((.)\\2*).+\\1";
System.out.println("aaa123aaa".matches(regex3));
System.out.println("aaa123abd".matches(regex3));
}
}
6666
-
非捕获分组(?: ?! ?=)仅仅是把数据括起来
-
不占用组号
package com.mohuanan.pazhong;
public class Demo06 {
public static void main(String[] args) {
String str = "莫莫莫华华南南";
String string = str.replaceAll("(.)\\1+", "$1");
System.out.println(string);
}
}
Date
package com.mohuanan.Time;
import java.util.Date;
import java.util.Random;
public class Demo01 {
public static void main(String[] args) {
//使用空参构造 创建时间对象
//当地时间
Date d1 = new Date();
System.out.println(d1);
//使用有参构造 创建时间对象
//从原点时间开始
Date d2 = new Date(1000l);
System.out.println(d2);
d2.setTime(8000l);
System.out.println(d2);
//获取的是从时间原点开始 到现在的毫秒值
long time = d1.getTime();
System.out.println(time);
Random r = new Random();
Date d3 = new Date(Math.abs(r.nextInt()));
Date d4 = new Date(Math.abs(r.nextInt()));
System.out.println(d3 + " " + d4);
//比较两个随机的时间
if (d3.getTime() > d4.getTime()) {
System.out.println("d4的时间在前面");
} else{
System.out.println("d3的时间在前面");
}
}
}
SimpleDateFormat
在Java中,SimpleDateFormat
是一个用于日期格式化和解析的类。它允许你将Date
对象转换为特定格式的字符串,或者将特定格式的字符串解析为Date
对象。这对于在用户界面上显示日期,或者在程序之间传递日期信息时特别有用。
作用
SimpleDateFormat
的主要作用有两个:
- 格式化:将
Date
对象转换为字符串,以便在用户界面上显示或存储。 - 解析:将字符串解析为
Date
对象,以便在程序中使用。
使用方法
使用SimpleDateFormat
的一般步骤如下:
- 创建实例:首先,你需要创建一个
SimpleDateFormat
的实例,并指定你想要的日期和时间格式。格式是由一系列的模式字母组成的字符串,例如"yyyy-MM-dd HH:mm:ss"表示年-月-日 时:分:秒。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- 格式化:使用
format
方法将Date
对象转换为字符串。
Date now = new Date();
String formattedDate = sdf.format(now);
System.out.println(formattedDate); // 输出类似于 "2024-04-16 17:09:03"
- 解析:使用
parse
方法将字符串解析为Date
对象。
String dateString = "2024-04-16 17:09:03";
Date parsedDate = sdf.parse(dateString);
注意事项
- 线程安全:
SimpleDateFormat
不是线程安全的。如果你在多线程环境中使用它,应该为每个线程创建单独的实例,或者使用ThreadLocal
来存储每个线程的实例。 - 解析错误:当解析字符串时,如果字符串的格式与
SimpleDateFormat
实例所期望的格式不匹配,会抛出ParseException
。为了避免这种情况,你可以使用setLenient(true)
来允许解析器在解析时更加宽容。 - 时区问题:
SimpleDateFormat
使用默认时区进行格式化和解析。如果你需要处理不同时区的日期和时间,应该明确设置时区。
常用和对打竞赛有帮助的方法
SimpleDateFormat
类的一些常用方法包括:
- format(Date date):将
Date
对象格式化为字符串。 - parse(String source):将字符串解析为
Date
对象。 - setLenient(boolean lenient):设置解析器是否宽松。如果为
true
,解析器将允许一些不严格的匹配。 - setTimeZone(TimeZone zone):设置时区。
- toPattern():返回此日期格式模式。
在打竞赛时,了解并熟练使用这些方法可以帮助你更高效地处理日期和时间相关的问题。特别是在需要按照特定格式读取或输出日期时,SimpleDateFormat
是一个非常有用的工具。同时,理解其线程安全性和异常处理机制也是非常重要的,可以避免在编程竞赛中出现一些常见的陷阱和错误。
package com.mohuanan.simple;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;
public class Demo01 {
public static void main(String[] args) throws ParseException {
//创建字符串
String date = "2023-11-11 11:11:11";
//创建SimpleDateFormat对象
//小细节: 创建对象的格式要和字符串的格式一样
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//解析
Date parse = sdf.parse(date);
System.out.println(parse.getTime());
}
}
Calendar
在Java中,Calendar
是一个抽象类,它提供了许多方法来处理日期和时间字段,如年、月、日、小时、分钟、秒等。Calendar
类是一个更灵活和强大的日期和时间处理工具,相比于早期的Date
类。
有什么用?
Calendar
类的主要用途包括:
- 获取和设置日期/时间的各个字段:例如,你可以获取或设置当前的年份、月份、日期等。
- 日期/时间的运算:你可以通过
Calendar
对象对日期和时间进行加法或减法运算,例如添加或减去特定的天数、月份等。 - 日期/时间的转换:
Calendar
类可以与Date
类进行转换,允许你在两者之间切换。
如何使用?
使用Calendar
类的一般步骤如下:
- 创建Calendar实例:通常使用
Calendar
类的静态方法getInstance()
来获取一个Calendar
对象,该对象表示当前日期和时间。
Calendar calendar = Calendar.getInstance();
- 获取或设置字段值:使用
get()
和set()
方法获取或设置日期和时间的各个字段。
int year = calendar.get(Calendar.YEAR);
calendar.set(Calendar.MONTH, Calendar.JANUARY);
- 日期/时间的运算:使用
add()
和roll()
方法进行日期和时间的运算。
calendar.add(Calendar.DAY_OF_MONTH, 1); // 明天
- 转换为Date对象(如果需要):
Date date = calendar.getTime();
注意事项:
- 月份是从0开始的:在
Calendar
中,月份是从0开始的,即0代表1月,1代表2月,依此类推。因此,在设置月份时,要注意这一点。 - 时区问题:
Calendar
对象默认使用系统时区。如果你需要处理不同时区的日期和时间,可能需要使用TimeZone
类。 - 线程安全性:
Calendar
类的实例不是线程安全的。如果你在多线程环境中使用它,需要确保线程安全,例如通过同步块或使用ThreadLocal
。
常用和对打竞赛有帮助的方法:
- 获取当前日期和时间:使用
getInstance()
方法。 - 日期/时间的比较:使用
before()
,after()
, 和equals()
方法。 - 日期/时间的运算:使用
add()
和roll()
方法。这两个方法的主要区别在于,add()
会考虑日期的连续性(例如,当添加一个月时,如果当前是1月31日,结果可能是3月2日或3日,取决于目标年份的2月有多少天),而roll()
则只简单地增加字段的值,不考虑日期的连续性。 - 设置字段的最小值和最大值:使用
set(int field, int value)
方法时,如果值超出该字段的有效范围,Calendar
会自动调整它。但是,你也可以使用getActualMinimum(int field)
和getActualMaximum(int field)
方法来获取某个字段的最小值和最大值。 - 转换为特定格式的字符串:虽然
Calendar
本身不提供直接的格式化方法,但你可以结合SimpleDateFormat
类来将日期和时间转换为特定格式的字符串,这在竞赛中经常需要。
总之,Calendar
类提供了强大的日期和时间处理能力,是Java中处理日期和时间的重要工具之一。在使用时,需要注意其特性和限制,并结合其他类(如Date
和SimpleDateFormat
)来满足具体需求。
jdk8新增的时间类
在Java 8中,引入了一套全新的日期和时间API,以替代之前不直观、易出错的java.util.Date
、java.util.Calendar
和java.text.SimpleDateFormat
等类。新的API位于java.time
包下,提供了更清晰、更易于使用的类来处理日期和时间。
新增的主要类及其作用
- LocalDateTime: 用于表示日期和时间(没有时区)。
- LocalDate: 仅用于表示日期(没有时间和时区)。
- LocalTime: 仅用于表示时间(没有日期和时区)。
- ZonedDateTime: 用于表示带有时区的日期和时间。
- Instant: 用于表示一个时间戳,通常是从1970-01-01T00:00:00Z开始的秒数和纳秒数的偏移量。
- Duration: 用于表示时间间隔,通常用于测量两个
Instant
之间的时间差。 - Period: 用于表示日期间隔,通常用于测量两个
LocalDate
之间的天数、月数或年数。
如何使用
下面是一些基本的使用示例:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TimeDemo {
public static void main(String[] args) {
// 获取当前日期和时间
LocalDateTime now = LocalDateTime.now();
System.out.println("Current date and time: " + now);
// 转换为带时区的日期和时间
ZonedDateTime zonedDateTime = now.atZone(ZoneId.systemDefault());
System.out.println("Current date and time with timezone: " + zonedDateTime);
// 添加和减去时间间隔
LocalDateTime later = now.plusDays(1);
LocalDateTime earlier = now.minusHours(2);
System.out.println("Later date and time: " + later);
System.out.println("Earlier date and time: " + earlier);
}
}
注意事项
- 线程安全性:这些新的日期和时间API的实例通常是不可变的,并且设计为线程安全的。这意味着它们可以作为常量安全地在多线程环境中使用。
- 时区处理:新的API提供了更好的时区支持,可以更容易地处理不同时区之间的转换。
- 格式化与解析:使用
DateTimeFormatter
类进行日期和时间的格式化和解析,这比旧的SimpleDateFormat
更加灵活和强大。 - 向后兼容性:虽然新的API提供了更好的功能和易用性,但旧的
java.util.Date
等类仍然存在于Java 8中,因此需要注意避免混用新旧API,以免造成混淆或错误。
常用和对打竞赛有帮助的方法
- 比较日期和时间:使用
isBefore()
,isAfter()
, 和isEqual()
方法来比较LocalDateTime
、LocalDate
、LocalTime
等实例。 - 获取特定字段:使用
getYear()
,getMonth()
,getDayOfMonth()
,getHour()
,getMinute()
,getSecond()
等方法获取日期和时间的特定字段。 - 操作日期和时间:使用
plusDays()
,plusWeeks()
,plusHours()
,minusMonths()
等方法来添加或减去时间间隔。 - 转换日期和时间:使用
atZone()
,toInstant()
,toLocalDate()
等方法在不同类型的日期和时间对象之间进行转换。 - 格式化:使用
DateTimeFormatter
的ofPattern()
方法和format()
方法来将日期和时间对象转换为字符串,或者使用parse()
方法将字符串解析为日期和时间对象。
在编程竞赛中,这些新的日期和时间API可以帮助你更快速、更准确地处理日期和时间相关的任务,减少错误并提高代码的可读性。
package com.mohuanan.chrono;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class Test01 {
public static void main(String[] args) {
//当前时间
LocalDateTime today = LocalDateTime.now();
//指定出生的时间
LocalDateTime birth = LocalDateTime.of(2005,8,12,0,0,0);
//分别计算间隔的时间
System.out.println(ChronoUnit.DAYS.between(birth,today));
System.out.println(ChronoUnit.YEARS.between(birth,today));
System.out.println(ChronoUnit.HOURS.between(birth,today));
//System.out.println(366*18);
}
}
包装类
package com.mohuanan.integer;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
//新的键盘录入
Scanner s = new Scanner(System.in);
//约定: 统一使用nextLine();
String str = s.nextLine();
int i = Integer.parseInt(str);
//double v = Double.parseDouble(str);
System.out.println(i);
//System.out.println(v);
}
}
在Java中,包装类(Wrapper Classes)是8种基本数据类型(byte, short, int, long, float, double, char, boolean)对应的类。包装类的主要作用是将基本数据类型封装成对象,以便在需要对象的地方使用基本数据类型。
包装类的作用:
- 对象化操作:Java是一种面向对象的语言,很多时候我们需要使用对象而不是基本数据类型。例如,当我们需要将基本数据类型作为参数传递给需要对象作为参数的方法时,就可以使用包装类。
- 提供更多的功能:包装类提供了很多实用的方法和常量,可以方便地进行数值计算、类型转换等操作。
- 自动装箱和拆箱:Java 5之后引入了自动装箱和拆箱的特性,使得基本数据类型和包装类之间的转换更加便捷。
如何使用包装类:
创建包装类对象的最直接方式是使用它们的构造函数,或者利用Java 5引入的自动装箱特性。
Integer i = new Integer(10); // 使用构造函数
Integer j = 10; // 使用自动装箱
int k = j.intValue(); // 使用自动拆箱,或者显式调用intValue()方法
注意事项:
- 缓存机制:对于Byte, Short, Integer, Long这四种包装类,Java为它们提供了缓存机制。具体来说,对于Byte, Short, Integer, 当数值在-128到127之间时,会缓存这些对象,不会创建新的对象;对于Long,这个范围是-128到127。超出这个范围的数值,会创建新的对象。
- null值:包装类对象是引用类型,可以赋值为null,这是基本数据类型所不具备的特性。
- 拆箱时的NullPointerException:在自动拆箱过程中,如果包装类对象为null,将会抛出NullPointerException。
常用和对打竞赛有帮助的方法:
- 类型转换:如
intValue()
,longValue()
,floatValue()
,doubleValue()
等,用于将包装类对象转换为对应的基本数据类型。 - 数值比较:
compareTo()
方法用于比较两个包装类对象的数值大小。 - 解析字符串为数值:如
Integer.parseInt(String s)
,Double.parseDouble(String s)
等,用于将字符串解析为对应的数值。 - 格式化数值为字符串:如
String.valueOf(int i)
,或者利用String.format()
方法结合包装类的静态方法(如Integer.toBinaryString(int i)
)来格式化数值。 - 位操作:包装类提供了一些位操作方法,如
Integer
类的bitCount()
,rotateLeft()
,toBinaryString()
等,这些方法在解决某些算法问题时可能很有用。
在编程竞赛中,熟练掌握包装类的使用,能够让你更灵活地处理数值问题,特别是在需要用到对象而不是基本数据类型时,包装类将是你的有力工具。同时,包装类提供的一些额外功能和方法,也能帮助你解决一些复杂的算法问题。