PHP8 —— New String Helpers

新增了三个字符串函数,str_starts_with, str_ends_with, str_contains, PHP 的函数这么方便,很难想象竟然一直没有这几个。 str_starts_with 判断字符串是否以另一个字符串开头,在PHP7以及之前 $id = 'inv_abcdefgh'; $result = strpos($id, 'inv_') === 0; var_dump($result); // true PHP8 中可以直接这么写 $result = str_starts_with($id, 'inv_'); str_ends_with 判断字符串是否以另外一个字符串结尾,在 PHP7 及之前,比较麻烦,通常是这么写 $id = 'abcd_inv'; $result = strpos(strrev($id), strrev('_inv')) === 0; 或者 $result = substr($id, -1 * strlen('_inv')) === '_inv'; 或者上正则吧 $result = preg_match('/_inv$/', $id) === 1; 看起来都是比较麻烦的。PHP8 里面可以简化成下面这样了 $id = 'abcd_inv'; $result = str_ends_with($id, '_ind'); str_contains 字符串包含,PHP8 之前一般就是 strpos 来实现了 $url = 'https://example?for=bar'; $result = strpos($url, '?') !== FALSE; PHP8 就直接一点 $result = str_contains($url, '?');

Java学习笔记 —— 给Map排序

Map接口包含一个称为Map.Entry的公共、静态、内部接口,该接口表示键值对。 Map.entrySet方法返回一组Map.Entry元素。 在Java 8之前,给map排序时主要使用接口中的getKey和getValue方法。 Java8 中,增加了下表中的静态方法。

方法 描述
comparingByKey(Comparator<? super K> cmp) Returns a comparator that comparesMap.Entryby key using the givenComparator
comparingByValue() Returns a comparator that comparesMap.Entryin natural order on value
comparingByValue(Comparator<?superV>cmp) ReturnsacomparatorthatcomparesMap.Entryby value using the givenComparator

下面用计算字典中单词长度和数量映射,来说明怎么使用这些方法。 Unix系统在/usr/share/dict/words目录中包含一个文件,保存了Webster第二版词典的内容。 我们用 Files.lines方法读取文件行并生成包含这些行的字符串流。

System.out.println("\nNumber of words of each length:"); 
try (Stream<String> lines = Files.lines(dictionary)) {
    lines.filter(s -> s.length() > 20) 
    .collect(Collectors.groupingBy(
        String::length, Collectors.counting()))
    .forEach((len, num) -> System.out.printf("%d: %d%n", len, num)); 
} catch (IOException e) {
        e.printStackTrace(); 
}

简要解释一下:

  • 使用 try-with-resources 块中在读取文件, Stream实现了 Auto Closeable,因此在try块退出时,Java会在Stream上调用close方法,然后在File上调用close方法。
  • filter 将处理范围限制为仅长度为20个字符以上的单词。
  • Collectors的groupingBy方法将Function作为第一个参数,表示分类器。在这里,分类器是每个字符串的长度。如果仅提供一个参数,则结果将一个Map,其中键是分类器的值,而值是与分类器匹配的元素的列表。groupingBy(String::length)会生成Map >,其中键是单词长度,值是该长度单词的列表。
  • 接受两个参数的 groupingBy ,可以提供另一个收集器(称为下游收集器),对单词列表进行后处理。返回类型为Map,其中键是单词长度,值是字典中该长度的单词数。

输出结果为:

Number of words of each length:
21: 82
22: 41
23: 17
24: 5

长度为21的字符的单词有82个,依次类推。 这个例子以map中单词长度的升序打印。 可以使用 Map.Entry.comparingByKey 来实现降序排列。

System.out.println("\nNumber of words of each length (desc order):");
try (Stream<String> lines = Files.lines(dictionary)) {
    Map<Integer, Long> map = lines.filter(s -> s.length() > 20).collect(Collectors.groupingBy(
        String::length, Collectors.counting()));
map.entrySet().stream().sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
    .forEach(e -> System.out.printf("Length %d: %2d words%n", e.getKey(), e.getValue()));
} catch (IOException e) {
    e.printStackTrace();
}

在计算Map 之后,提取entrySet并生成一个流。 Stream 上的 sorted 接受比较器,生成排序后的流。Map.Entry.comparingByKey接受一比较器(指定倒序),生成一个按键排序的比较器,

程序输出为:

Number of words of each length (desc order):
Length 24:  5 words
Length 23: 17 words
Length 22: 41 words
Length 21: 82 words

评论

此博客中的热门博文

D3js Data-binding basics

JavaScript 数据类型

Vue3新特性(1) —— Vite