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 对
1
2Locale 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 对象匹配一个字符串,返回匹配结果
1
2
3
4private 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)
1
2
3
4while (m.find()) {
System.out.println("start(): " + m.start()); //开始位置
System.out.println("end(): " + m.end()); //结束位置
}- Study Methods(查找方法)
- lookingAt(), find(), find(int start), matches()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private 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 方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private 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());
}replaceAll 方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private 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());
}
-
其他字符串操作
-
字符串和集合互转
- [1,2,3], “1,2,3”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import 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); -
字符串转义
- 对关键字符转义
1
2
3
4
5
6
7
8
9
10import 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); -
变量名字格式化
- 名字驼峰命名
1
2
3
4import 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 实现原理)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import 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());
}
Leave a comment