第7章 java基础类库(下)
来源:互联网 发布:服务器软件有哪些 编辑:程序博客网 时间:2024/06/08 19:09
Java8的日期、时间类
Date类无法实现国际化,而且对不同属性也使用了前后矛盾的偏移量
Calendar类过于复杂
Java8吸收Joda-Time的经验,提供了一套全新的日期时间库
- Date类
Java官方推荐尽量少用Date类(java.util.Date)的构造器和方法,若有需要可使用Calendar工具类
- Calendar类
是抽象类,所以不能通过构造器创建对象,而是提供了几个静态getInstance()方法,根据TimeZone、Locale来获取指定的Calendar
Calendar与Date类相互转换
public class Test { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); Date date = cal.getTime(); Calendar cal2 = Calendar.getInstance(); cal2.setTime(date); }}
Calendar类用法
package chapter7.four;import java.util.Calendar;import static java.util.Calendar.*;/** * Created by dongyu.liu on 2016/10/27. */public class CalendarTest { public static void main(String[] args) { Calendar c = Calendar.getInstance(); // 年 System.out.println(c.get(YEAR));// 2016 c.get(int field) c.add(1, 10);// System.out.println(c.get(YEAR));// 2026 // 月 System.out.println(c.get(MONTH));// 9 月份的起始月是0不是1,所以9代表10月 // 日 System.out.println(c.get(DATE));// 27 c.set(2003,10,23,12,32,23); c.add(YEAR,10);// 2013 System.out.println(c.getTime());// 2013-11-23 12:32:23 // 月向前推8个月 c.roll(MONTH,-8);// // 2013-3-23 12:32:23 System.out.println(c.getTime()); // 指定日历字段可能的最大值 System.out.println(c.getActualMaximum(MONTH));// 11 // 最小值 System.out.println(c.getActualMinimum(MONTH));// 0 }}
add(int field,int amount)和roll(int field ,int amount)的区别
// add 与 roll的区别 Calendar c1 = Calendar.getInstance(); c1.set(2003,7,23,0,0,0);// 2003-8-23 Calendar c2 = Calendar.getInstance(); c2.set(2003,7,23,0,0,0);// 2003-8-23 // 如果上级字段需要改变 add的上级字段会改变,roll的上级字段不会改变 c1.add(MONTH,6); System.out.println(c1.getTime());// 2004-2-23 上级字段会增大 c2.roll(MONTH,6); System.out.println(c2.getTime());// 2003-2-23 上级字段不会增大 // 如果下级字段需要改变,二者处理方式相同,下级字段会修正到变化最小的值 Calendar c3 = Calendar.getInstance(); c3.set(2003,7,31,0,0,0);// 2003-8-23 c3.add(MONTH,6); System.out.println(c1.getTime());// 2004-2-29 Calendar c4 = Calendar.getInstance(); c4.set(2003,7,31,0,0,0);// 2003-8-23 c4.roll(MONTH,6); System.out.println(c4.getTime());// 2003-2-29
calendar可设置容错性,若容错性关闭,则set传入的field只能在指定的范围内(如MONTH是0-11),否则报错
c4.setLenient(false);
set(f,value)方法具有延迟修改的特性,即多次调用set()方法时,calendar所代表的时间不会立即被修改,但系统会有记录(多次set(f,value)是叠加的效果),
当调用get(),getTime(),getTimeInMillis(),add(),或roll()时才重新计算calendar所代表的时间
* Java8新增的日期、时间包
package chapter7.four;import java.time.*;/** * Created by dongyu.liu on 2016/10/29. */public class NewDatePackageTest { public static void main(String[] args) { //-------------Clock类-------------------- // 该类用于获取指定时区的当前日期、时间。该类可取代System.currentTimeMillis()方法 Clock clock = Clock.systemUTC(); System.out.println("当前时刻为"+clock.instant());// 当前时刻为2016-10-29T06:55:19.777Z // 获取clock对应的毫秒数 System.out.println(clock.millis()==System.currentTimeMillis());// true //-------------Duration类-------------------- // 代表持续时间,可方便的获取一段时间 Duration d = Duration.ofSeconds(6000); System.out.println(d.toMinutes());// 100 System.out.println(d.toHours());// 1 System.out.println(d.toDays());// 0 // 在Clock基础上增加6000秒,返回新的Clock Clock clock2 = Clock.offset(clock,d); System.out.println(clock2.instant());//2016-10-29T08:35:20.430Z 与clock时间相差1小时40分 //-------------Instant类-------------------- // 代表一个具体的时刻,可以精确到纳秒 Instant instant = Instant.now(); // 获取当前时间 System.out.println(instant);//2016-10-29T06:57:52.516Z Instant instant2 = instant.plusSeconds(6000); System.out.println(instant2);// 增加6000秒 // 根据字符串解析instant对象 Instant instant3 = Instant.parse("2016-10-29T06:57:52.516Z"); System.out.println(instant3); // 在instant3的基础上添加5小时4分钟 Instant instant4 = instant3.plus(Duration.ofHours(5).plusMinutes(4)); System.out.println(instant4); // 获取instant4五天以前的实例 System.out.println(instant4.minus(Duration.ofDays(5))); //-------------LocalDate类-------------------- // 该类代表不带时区的日期 例如: 2007-12-03 LocalDate localDate = LocalDate.now(); System.out.println(localDate); // 获得2014年的第146天 localDate = LocalDate.ofYearDay(2014, 146); System.out.println(localDate); // 设置为2014年5月21日 localDate = LocalDate.of(2014, Month.MAY, 21); System.out.println(localDate); //-------------LocalTime类-------------------- // 代表不带时区的时间,例如10:15:30 LocalTime localTime = LocalTime.now(); localTime = LocalTime.of(22,33); System.out.println(localTime);// 22:33 // 返回一天中的第5503秒 localTime = LocalTime.ofSecondOfDay(5503); System.out.println(localTime);// 01:31:43 //-------------LocalDateTime类-------------------- // 代表不带时区的日期、时间 例如: 2007-12-03T10:15:30 LocalDateTime localDateTime = LocalDateTime.now(); // 当前日期加上25小时3分钟 LocalDateTime future = localDateTime.plusHours(25).plusMinutes(3); System.out.println(future);// 2016-10-30T16:26:23.811 //-------------Year YearMonth MonthDay类-------------------- // MonthDay代表月日 --04-12 // Year代表年 2014 // YearMonth 代表年月 2014-04 Year year = Year.now(); System.out.println(year);// 2016 year = year.plusYears(5); System.out.println(year);// 2021 // 根据指定月份获取YearMonth YearMonth ym = year.atMonth(10); System.out.println(ym);// 2021-10 // 当前年月再加5年减3个月 System.out.println(YearMonth.now().plusYears(5).minusMonths(3));// 2021-07 // 月日 System.out.println(MonthDay.now());// --10-29 // 设置为5月23日 MonthDay md2 = MonthDay.now(); System.out.println(MonthDay.now().with(Month.MAY).withDayOfMonth(23));// --05-23 }}
4.正则表达式
正则表达式是一种强大的字符串处理工具(用于匹配字符串的模板),可以对字符串进行查找、提取、分割、替换等操作。
String类中提供了几个特殊的方法:matches()、replaceAll()、replaceFirst()、split()()
Pattern和Matcher两个类专门用于提供正则表达式支持
- 创建正则表达式
- 合法字符
- 特殊字符
- 预定义字符
- 方括号表达式
- 圆括号表达式
- 边界匹配符
- 数量标识符(贪婪模式(默认)、勉强模式、占有模式)
String str = "hello , java";// 贪婪模式的正则表达式System.out.println(str.replaceFirst("\\w*","@"));// @ , java// 勉强模式的正则表达式System.out.println(str.replaceFirst("\\w*?","@"));// @hello , java
"\u0041\\\\" // 匹配A\"\u0061\t" // 匹配a<制表符>"\\?\\[" // 匹配?[
预定义字符(通配符)
. 匹配任何字符
\d 匹配0-9的所有数字(digit)
\D 匹配非数字
\s 匹配空白字符、包括空格、制表符、回车符、换页符、换行符等(space)
\S 匹配非空白字符
\w 匹配所有的单词字符,包括0-9所有数字、26个英文字符和下划线(word)
\W 匹配所有的非单词字符
c\\w //可以匹配cat、cbt、cct c0t c9t等一批字符串\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d //匹配如 000-000-0000形式的电话号码((private)|(protected)|(public)) // 匹配java的三个访问控制符之一
- 使用正则表达式
一旦在程序中定义了正则表达式,就可以使用Pattern和Matcher来使用正则表达式。
Pattern对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须被编译为pattern对象,
然后再利用该Pattern对象创建对应的Matcher对象。多个Matcher对象可共享同一个Pattern对象。
// 将一个正则表达式便以为Pattern对象 Pattern p = Pattern.compile("a*b"); // 使用Pattern对象创建Matcher对象 Matcher m = p.matcher("aaaaab"); boolean b = m.matches(); System.out.println(b);// true// 如果某个正则表达式仅需一次使用 但下面的方式要每次重新编译Pattern对象,所以效率不高 boolean c = Pattern.matches("a*b", "aaaaab");
Patter类是不可变类,可供多个并发线程安全使用
Matcher类中的常用方法:
find():返回目标字符串是否包含与Pattern匹配的子串
group():返回上一次与Pattern匹配的子串
start(): 上次匹配的字符串在目标字符串中的开始位置
end(): 上次匹配的字符串在目标字符串中的结束位置加1
lookingAt():返回目标字符串前面部分与Pattern是否匹配
matches():返回是否匹配
reset():将现有的Macher对象应用于一个新的字符序列
CharSequence接口,CharBuffer String StringBuffer StringBuilder 都是它的实现类,它代表一个各种表示形式的字符串
模拟互联网网络爬虫
public class FindGroup { public static void main(String[] args) { String s = "lalsdfidsjdsfd13588886666fdsonsdcdso" + "dovdskfkmods15822223333dfjidsoc" + "158222jofsdf135dsfodsff"; Pattern p = Pattern.compile("((13\\d)|(15\\d))\\d{8}"); Matcher m = p.matcher(s); while(m.find()){ System.out.println(m.group());// 13588886666 15822223333 } }}
start() end()
public class StartEnd { public static void main(String[] args) { String regStr = "java is very easy!"; Matcher m = Pattern.compile("\\w+").matcher(regStr); while(m.find()){ System.out.println(m.group()+"子串的起始位置是:"+m.start()+"结束位置是:"+m.end());// java子串的起始位置是:0结束位置是:4// is子串的起始位置是:5结束位置是:7// very子串的起始位置是:8结束位置是:12// easy子串的起始位置是:13结束位置是:17 } }}
LookingAt():只要以Pattern开头就返回true
matches(): 要求完全匹配才可以
reset():将现有的Macther对象用于新的字符串序列
public class MatchesTest { public static void main(String[] args) { String[] mails = { "dfisdof@fds.com", "sdfods@dsfd.com", "dsfojs@jdsojf.org", "dsfodsj@dsf.xx" }; String mailRegex = "\\w{3,20}@\\w+\\.(com|org|cn)"; Pattern p = Pattern.compile(mailRegex); Matcher m = null; for (String mail:mails){ System.out.println(mail.matches(mailRegex));// 利用字符串的api true true true false } for (String mail : mails) { if (m == null) { m = p.matcher(mail); } else { m.reset(mail); } System.out.println(mail + (m.matches() ? "是" : "不是") + "一个有效地址"); } for (String mail : mails) { m = p.matcher(mail); System.out.println(mail + (m.matches() ? "是" : "不是") + "一个有效地址");// dfisdof@fds.com是一个有效地址// sdfods@dsfd.com是一个有效地址// dsfojs@jdsojf.org是一个有效地址// dsfodsj@dsf.xx不是一个有效地址 } }}
分割、查找、替换
可以使用Matcher类提供的replaceAll() replaceFirst()方法
也可以使用String类提供的replaceFirst() split()等方法
增加了正则表达式支持的Java StringTokenizer类可不使用(没有正则表达式强大)
public class StringRegTest { public static void main(String[] args) { String[] msgs = {"regd ref ds","re re","dfd re "}; for(String msg:msgs) { System.out.println(msg.replaceFirst("re\\w*", "哈哈哈")); System.out.println(Arrays.toString(msg.split(" "))); } }}
国际化与格式化
国际化 I18N Internationalization
本地化 L10N Localization
Java8的国际化支持升级到了Unicode6.2.0字符集
- Java的国际化思路
java程序的国际化思路时将程序中的标签、提示等信息放在资源文件中,程序需要支持哪些国家、
语言环境,就对应提供相应的资源文件。
主要通过下面三个类完成:
1. java.util.ResourceBundle:用于加载国家、语言资源包
2. java.util.Locale:用于封装特定的国家/区域、语言环境
3. java.text.MessageFormat:用于格式化带占位符的字符串
资源文件名有三种命名方式:
- baseName.language_country.properties
- baseName.language.properties
- baseName.properties
baseName可随意指定,language和country必须是java支持的语言
- Java支持的国家和语言
public class LocalList { public static void main(String[] args) { // 返回Java所支持的全部国家和语言的数组 Locale[] localList = Locale.getAvailableLocales(); // 遍历数组的每个元素,依次获取所支持的国家和语言 for (Locale l : localList) { System.out.println(l.getDisplayCountry() + "=" + l.getCountry() + " " + l.getDisplayLanguage() + "=" + l.getLanguage()); }// = 中文=zh// 马其顿王国=MK 马其顿文=mk// 白俄罗斯=BY 白俄罗斯文=be// 斯洛文尼亚=SI 斯洛文尼亚文=sl// 秘鲁=PE 西班牙文=es// 印度尼西亚=ID 印度尼西亚文=in// 英国=GB 英文=en // ...... }}
完成程序格式化
- 添加配置文件
mess_en_US.properties
- 添加配置文件
mess_zh_CN.properties hello=你好!
2. java代码
public class HelloI18NTest { public static void main(String[] args) { Locale locale = Locale.getDefault(Locale.Category.FORMAT); System.out.println(locale.getDisplayCountry()+locale.getCountry());// 中国CN System.out.println(locale.getDisplayLanguage()+locale.getLanguage());// 中文zh // 根据local判断要加载哪个配置文件 mess_en_US.properties mess_zh_CN.properties ResourceBundle bundle = ResourceBundle.getBundle("chapter7.six.mess",locale); System.out.println(bundle.getString("hello")); }}
使用MessageFormat处理包含占位符的字符串
- 配置文件
mess_zh_CN.properties
hello=你好,{0}!今天是{1}
public class HelloArg { public static void main(String[] args) { Locale currentLocale = Locale.getDefault(Locale.Category.FORMAT); ResourceBundle bundle = ResourceBundle.getBundle("chapter7.six.mess", currentLocale); String msg = bundle.getString("hello"); System.out.println(MessageFormat.format(msg,"yeeku",new Date()));// 你好,yeeku!今天是16-10-30 下午2:08 }}
- 使用类文件代替资源文件
java允许使用类文件代替资源文件,必须满足以下条件:
1. 类名必须是baseName.language_country.properties
2. 必须继承ListResourceBundle,并重写getContents()方法,该方法返回Object数组
类文件
public class mess_zh_CN extends ListResourceBundle { private final Object[][] myData = { {"hello","{0},你好!今天的日期时{1}"}, {"hello2","{0},你好!我是类文件代替资源文件哦!今天的日期时{1}"}, }; @Override protected Object[][] getContents() { return myData; }}
调用方法
public class HelloArg { public static void main(String[] args) { Locale currentLocale = Locale.getDefault(Locale.Category.FORMAT); ResourceBundle bundle = ResourceBundle.getBundle("chapter7.six.mess", currentLocale); String msg = bundle.getString("hello2");// yeeku,你好!我是类文件代替资源文件哦!今天的日期时16-10-30 下午2:29 System.out.println(MessageFormat.format(msg,"yeeku",new Date())); }}
ResouceBundle搜索资源文件的顺序是:
- baseName_zh_CN.class
- baseName_zh_CN.properties
- baseName_zh.class
- baseName_zh.properties
- baseName.class
baseName.properties
- 使用NumberFormat格式化数字
用于实现数字格式化,是抽象类Format的子类,它也是一个抽象基类
NumberFormat有国际化的作用
public static void main(String[] args) { double db = 213.3243354; Locale[] locales = {Locale.CHINA, Locale.JAPAN, Locale.GERMAN, Locale.US}; NumberFormat[] nf = new NumberFormat[12]; for (int i = 0; i <locales.length ; i++) { nf[i * 3] = NumberFormat.getNumberInstance(locales[i]); nf[i * 3 + 1] = NumberFormat.getPercentInstance(locales[i]); nf[i * 3 + 2] = NumberFormat.getCurrencyInstance(locales[i]); } for (int i = 0; i <locales.length ; i++) { String tip = i == 0 ? "-----中国的格式------" : i == 1 ? "-日本格式--" : i == 2 ? "---德国格式-----" : "--美国格式----"; System.out.println(tip); System.out.println("通用数值格式:"+nf[i*3].format(db)); System.out.println("百分比数值格式:"+nf[i*3+1].format(db)); System.out.println("货币数值格式:"+nf[i*3+2].format(db));// -----中国的格式------// 通用数值格式:213.324// 百分比数值格式:21,332%// 货币数值格式:¥213.32// -日本格式--// 通用数值格式:213.324// 百分比数值格式:21,332%// 货币数值格式:¥213// ---德国格式-----// 通用数值格式:213,324// 百分比数值格式:21.332%// 货币数值格式:¤ 213,32// --美国格式----// 通用数值格式:213.324// 百分比数值格式:21,332%// 货币数值格式:$213.32 } }
- 使用DateFormat格式化日期、时间
用于实现日期格式化,是抽象类Format的子类,它也是一个抽象类
获得DateFormat后 可调用setLenient(boolean lenient)来设置是否使用严格语法
DateFormat的parse可以将字符串解析成Date对象,但要求被解析的字符串必须符合要求
String str1 = "2014-12-12"; String str2 = "2014年12月10日"; System.out.println(DateFormat.getDateInstance().parse(str1));// Fri Dec 12 00:00:00 CST 2014 System.out.println(DateFormat.getDateInstance().parse(str2));// 报错
public class DateFormatTest { public static void main(String[] args) { Date dt = new Date(); Locale[] locales = {Locale.CHINA, Locale.US}; DateFormat[] df = new DateFormat[16]; // 为上面两个Locale创建16个DateFormate对象 for (int i = 0; i <locales.length ; i++) { df[i * 8] = DateFormat.getDateInstance(SHORT,locales[i]); df[i * 8+1] = DateFormat.getDateInstance(MEDIUM,locales[i]); df[i * 8+2] = DateFormat.getDateInstance(LONG,locales[i]); df[i * 8+3] = DateFormat.getDateInstance(FULL,locales[i]); df[i * 8+4] = DateFormat.getTimeInstance(SHORT, locales[i]); df[i * 8+5] = DateFormat.getTimeInstance(MEDIUM, locales[i]); df[i * 8+6] = DateFormat.getTimeInstance(LONG, locales[i]); df[i * 8+7] = DateFormat.getTimeInstance(FULL, locales[i]); } for (int i = 0; i <locales.length; i++) { System.out.println(i==0?"----中国的时间格式----":"---美国日期格式----"); System.out.println(df[i*8].format(dt)); System.out.println(df[i*8+1].format(dt)); System.out.println(df[i*8+2].format(dt)); System.out.println(df[i*8+3].format(dt)); System.out.println(df[i*8+4].format(dt)); System.out.println(df[i*8+5].format(dt)); System.out.println(df[i*8+6].format(dt)); System.out.println(df[i*8+7].format(dt)); } }}
- 使用SimpleDateFormat格式化日期
解决DateFormat不够灵活的问题 比如parse()方法要求字符串必须是特定格式
public class SimpleDateFormatTest { public static void main(String[] args) throws ParseException { Date d = new Date(); SimpleDateFormat sdf1 = new SimpleDateFormat("Gyyyy年中第D天"); String dateStr = sdf1.format(d); System.out.println(dateStr);// 公元2016年中第304天 // 一个非常特殊的日期字符串 String str = "14###三月##21"; SimpleDateFormat sdf2 = new SimpleDateFormat("y###MMM##d"); System.out.println(sdf2.parse(str));// Fri Mar 21 00:00:00 CST 2014 }}
Java8新增的日期、时间格式器
java.time.format包下提供了一个DateTimeFormatter格式器类,
相当于DateFormat和SimpleDateFormat的合体,功能非常强大
- 使用DateTimeFormatter完成格式化
public class NewFormatterTest { public static void main(String[] args) { DateTimeFormatter[] formatters = new DateTimeFormatter[]{ // 直接使用常量创建DateTimeFormatter格式器 DateTimeFormatter.ISO_LOCAL_DATE, DateTimeFormatter.ISO_LOCAL_TIME, DateTimeFormatter.ISO_LOCAL_DATE_TIME, //使用本地化的不同风格来创建DateTimeFormatter格式器 DateTimeFormatter.ofLocalizedDateTime(FULL, MEDIUM), DateTimeFormatter.ofLocalizedDate(LONG), // 根据模式字符串来创建DateTimeFormatter格式器 DateTimeFormatter.ofPattern("Gyyy%%MMMdd HH:mm:ss")}; LocalDateTime date = LocalDateTime.now();// 依次使用不同的格式器对LocalDateTime进行格式化 for (int i = 0; i < formatters.length; i++) { // 下面两行代码作用相同 System.out.println(date.format(formatters[i])); System.out.println(formatters[i].format(date));// 2016-10-30// 2016-10-30// 15:47:01.667// 15:47:01.667// 2016-10-30T15:47:01.667// 2016-10-30T15:47:01.667// 2016年10月30日 星期日 15:47:01// 2016年10月30日 星期日 15:47:01// 2016年10月30日// 2016年10月30日// 公元2016%%十月30 15:47:01// 公元2016%%十月30 15:47:01 } }}
- 使用DateTimeFormatter解析字符串
public class NewFormatterParse { public static void main(String[] args) { String str1 = "2014==04==12 01时06分09秒"; DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy==MM==dd HH时mm分ss秒"); // 执行解析 LocalDateTime dt1 = LocalDateTime.parse(str1, formatter1); System.out.println(dt1);// 2014-04-12T01:06:09 System.out.println(dt1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));// 2014-04-12 01:06:09 }}
本章小结
- 第7章 java基础类库(下)
- 第7章 Java基础类库(上)
- 《Java程序设计基础》 第7章手记
- Java程序设计基础-第7章
- java基础 第6章类再生
- 黑马程序员——Java基础---多线程(下)--第12天--第142-151集
- java基础第7天
- java基础第7天
- 第2章 Java基础
- Java基础(下)
- 第2章 JavaScript语言基础(下)
- 黑马程序员——Java基础语法(二)---流程控制(下)--第3天--第31-41集
- 黑马程序员——Java基础语法(三)---数组(下)--第4天--第48-61集
- 黑马程序员——Java基础---面向对象(异常(下))--第10天--第118-123集
- 黑马程序员——Java基础---网络编程(下)--第24天--第302-311集
- 黑马程序员——Java基础---面向对象(抽象类)--第7天--第90-93集
- 第04章-VTK基础(7)
- 黑马程序员----Java基础第7天(抽象类,继承,final,接口)
- 2016ACM亚洲赛沈阳站 E - 暴搜
- javaweb中HTTP协议的幂等性
- HDU 2087 剪花布条(哈希写法)
- Java编程基础-标识符
- HDU_1272_小希的迷宫
- 第7章 java基础类库(下)
- POJ 3186Treats for the Cows 递推
- HDU 2082 普通母函数
- 【NOIP2008】 CODE[VS] 1169 传纸条(棋盘型DP)
- 前端CSS规范整理
- do语句的使用
- CodeForces 444C. DZY Loves Physics
- 436. Find Right Interval
- HDU1200——To and Fro