MOOC 个人学习笔记
# 1. 国际化编程
- Java 是第一个设计成支持国际化的编程语言
- java.util.ResourceBundle 用于加载一个语言_国家语言包
- java.util.Locale 定义一个语言_国家
- java.text.MessageFormat 用于格式化带占位符的字符串
- java.text.NumberFormat 用于格式化数字 / 金额
- java.text.DateFormat 用于格式化日期时间
- java.time.format.DateTimeFormatter 用于格式化日期时间
# Locale 类
- Locale(zh_CN, en_US,…)
- 语言,zh,en 等
- 国家 / 地区,CN,US 等
- 其他变量 (variant)(几乎不用)
- Locale 方法
- getAvailableLocales () 返回所有的可用 Locale
- getDefault () 返回默认的 Locale
# 语言文件
- 一个 Properties 文件
- 包含 K-V 对,每行一个 K-V,例如:age=20
- 命名规则
- 包名_语言_国家地区.properties, (语言和国家地区可选)
e.g. message_zh_CN.properties - 存储文件必须是 ASCII 码文件
- 如果是 ASCII 以外的文字,必须用 Unicode 的表示 \uxxxx
- 可以采用 native2ascii.exe (% JAVA_HOME%\bin 目录下) 进行转码
- 包名_语言_国家地区.properties, (语言和国家地区可选)
# ResourceBundle 类
- ResourceBundle
- 根据 Locale 要求,加载语言文件 (Properties 文件),存储 K-V 对
Locale myLocale = new Locale("zh", "CN");
ResourceBundle.getBundle("msg", myLocale); // 加载 msg_zh_CN.properties
- getString (String key) 返回所对应的 value
- 如果找不到 key,则报异常
- 语言文件层级结构
- 文件:包名_当前 Locale 语言_当前 Locale 国家地区_当前 Locale 变量 (variant)
- msg_zh_CN.properties (注意大小写)
- msg_zh.properties
- msg.properties
- 文件形成树结构
- ResourceBundle 加载文件
- 首先,按如下顺序找到第一个 Properties 文件
- 包名_当前 Locale 语言_当前 Locale 国家地区_当前 Locale 变量 (variant)
- 包名_当前 Locale 语言_当前 Locale 国家地区
- 包名_当前 Locale 语言
- 包名_默认 Locale 语言_默认 Locale 国家地区_默认 Locale 变量 (variant)
- 包名_默认 Locale 语言_默认 Locale 国家地区
- 包名_默认 Locale 语言
- 包名
- 根据 Properties 树结构,把第一步的 Properties 文件及父级文件全部加载,作为后续的 K-V 集合
# 2. 高级字符串处理
# 正则表达式
- 用事先定义好的一些特定字符、及这些特定字符的组合,组成一个 “规则字符串”
- 作用
- 测试字符串内的模式
- 识别 / 替换文本
- 提取文本
# java.util.regex 包
- Pattern 类 正则表达式的编译表示
- compile 编译一个正则表达式为 Pattern 对象
- matcher 用 Pattern 对象匹配一个字符串,返回匹配结果
private static final String REGEX = "\\bdog\\b"; //\b 表示边界
private static final String INPUT = "dog dog dog doggie dogg";
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
- Matcher 类
- Index Methods (位置方法)
- start(), start(int group), end(), end(int group)
while (m.find()) {
System.out.println("start(): " + m.start()); // 开始位置
System.out.println("end(): " + m.end()); // 结束位置
}
- Study Methods (查找方法)
- lookingAt(), find(), find(int start), matches()
private static final String REGEX = "foo";
private static final String INPUT = "foooooooo";
private static Pattern pattern;
private static Matcher matcher;
public static void main(String[] args) {
// Initialize
pattern = Pattern.compile(REGEX);
matcher = pattern.matcher(INPUT);
System.out.println("Current REGEX is: " + REGEX);
System.out.println("Current INPUT is: " + INPUT);
System.out.println("lookingAt(): " + matcher.lookingAt()); // 部分匹配
System.out.println("matches(): " + matcher.matches()); // 完全匹配
}
- Replacement Methods (替换方法)
- replaceAll(String replacement)
- appendReplacement 方法:replaceAll 方法:
private static String REGEX = "a*b"; //* 表示限定前面的 a 可以有 0 或者多个。
private static String INPUT = "aabfooaabfooabfoobcdd";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT); // get a matcher object
StringBuffer sb = new StringBuffer();
// 全部替换
while(m.find()){
m.appendReplacement(sb,REPLACE);
}
// 将最后的尾巴字符串附加上
m.appendTail(sb);
System.out.println(sb.toString());
}
private static String REGEX = "a*b"; //* 表示限定前面的 a 可以有 0 或者多个。
private static String INPUT = "aabfooaabfooabfoobcdd";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT); // get a matcher object
StringBuffer sb = new StringBuffer();
// 全部替换
while(m.find()){
m.appendReplacement(sb,REPLACE);
}
// 将最后的尾巴字符串附加上
m.appendTail(sb);
System.out.println(sb.toString());
}
- appendReplacement 方法:
# 其他字符串操作
- 字符串和集合互转
- [1,2,3], “1,2,3”
import org.apache.commons.lang3.StringUtils;
List<String> names = new LinkedList<String>();
names.add("Xiaohong");
names.add("Xiaoming");
names.add("Daming");
names.add("Xiaohei");
// 从 ArrayList 变到字符串
String str1 = String.join(",", names); //String.join, JDK 8 引入
System.out.println(str1);
String str2 = StringUtils.join(names, ","); //Apache Commons Lang
System.out.println(str2);
// 从字符串变回 ArrayList
List<String> names2 = Arrays.asList(str2.split(","));
for(String name:names2) {
System.out.println(name);
}
//StringUtils 可以支持更多数据类型
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(3);
ids.add(5);
String str3 = StringUtils.join(ids, ",");
System.out.println(str3);
- 字符串转义
- 对关键字符转义
import org.apache.commons.text.StringEscapeUtils;
String str = "He didn't say, \"Stop!\"";
// 转义
String escapedStr = StringEscapeUtils.escapeJava(str);
System.out.println("escape" + ":" + escapedStr);
// 从转义字符串转回来
String str2 = StringEscapeUtils.unescapeJava(escapedStr);
System.out.println("unescape" + ":" + str2);
- 变量名字格式化
- 名字驼峰命名
import com.google.common.base.CaseFormat;
String s1 = "CONSTANT_NAME";
String s2 = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, s1);
System.out.println(s2); //constantName;
- 字符串输入流
- 将字符串转为一个输入流
- 输入流可以定义为 Scanner(OJ 实现原理)
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
// 构造字符串列表
List<String> names = new LinkedList<String>();
names.add("Xiaohong");
names.add("Xiaoming");
names.add("Daming");
names.add("Xiaohei");
// 合并为一个字符串,以逗号相连
String nameStr = String.join(",",names);
// 将字符串作为默认的输入流
InputStream in = IOUtils.toInputStream(nameStr, Charsets.toCharset("UTF-8"));
// 重置系统的输入流
System.setIn(in);
// 模拟键盘输入 这也是 OJ 平台测试用例输入的原理
// 此处也可以换成一个文件输入流
Scanner sc=new Scanner(System.in);
sc.useDelimiter(",");
while(sc.hasNext())
{
System.out.println(sc.next());
}