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

# ResourceBundle 类

  1. ResourceBundle
  • 根据 Locale 要求,加载语言文件 (Properties 文件),存储 K-V 对
    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 对象匹配一个字符串,返回匹配结果
    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 方法:
        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 方法:
        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”
    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());
    }