少女祈祷中...

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目录下)进行转码

ResourceBundle类

  1. ResourceBundle
  • 根据Locale要求,加载语言文件(Properties文件),存储K-V对
    1
    2
    Locale myLocale = new Locale("zh", "CN");
    ResourceBundle.getBundle("msg", myLocale); //加载msg_zh_CN.properties
  • getString(String key) 返回所对应的value
    • 如果找不到key,则报异常
  1. 语言文件层级结构
  • 文件: 包名_当前Locale语言_当前Locale国家地区_当前Locale变量(variant)
    • msg_zh_CN.properties (注意大小写)
    • msg_zh.properties
    • msg.properties
  • 文件形成树结构
  1. 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
    4
    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)
    1
    2
    3
    4
    while (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
    16
    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方法:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        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());
        }
        replaceAll方法:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        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());
        }

其他字符串操作

  • 字符串和集合互转
    • [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
    28
    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);
  • 字符串转义
    • 对关键字符转义
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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);
  • 变量名字格式化
    • 名字驼峰命名
    1
    2
    3
    4
    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实现原理)
    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
    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());
    }