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 学习笔记 —— 从 Optional 中获取值

可以使用get方法获取Optinal中的值,但是,如果Optional为空,get方法将引发NoSuchElementException。
举个🌰:

Optional<String> firstEven =
    Stream.of("five", "even", "length", "string", "values")
    .filter(s -> s.length() % 2 == 0)
    .findFirst();

findFirst方法返回Optional ,Stream中可能所有的值都不符合条件。如果我们用Optional的get来打印返回的值:

System.out.println(firstEven.get()) // Don't do this, even if it works

除非能够100%确定Optional一定不为空才可以这么使用,否则程序会抛异常,如以下示例所示。

Optional<String> firstOdd =
    Stream.of("five", "even", "length", "string", "values")
    .filter(s -> s.length() % 2 != 0) 
    .findFirst();

System.out.println(firstOdd.get()); // throws NoSuchElementException

如何解决这个问题?有几种选择。第一种方案,先判断Optional是否包含值,然后再获取。

Optional<String> firstEven =
    Stream.of("five", "even", "length", "string", "values")
    .filter(s -> s.length() % 2 == 0)
    .findFirst();

System.out.println(first.isPresent() ? first.get() : "No even length strings");

这种方法不过是把原来的null检查替换为isPresent检查,使用Optional 的优势完全丧失了。
第二种方式,是使用orElse方法,如下所示。

Optional<String> firstOdd =
    Stream.of("five", "even", "length", "string", "values")
    .filter(s -> s.length() % 2 != 0)
    .findFirst();

System.out.println(firstOdd.orElse("No odd length strings"));

如果存在一个值,则orElse方法返回所包含的值,否则返回所提供的默认值。因此,在可以提供默认值的情况下,这是一种方便使用的方法。orElse有一些变体:

  • orElse(T other)返回值(如果存在),否则返回默认值 other
  • orElseGet(Supplier <?extended T> other)结果存时返回结果,否则调用Supplier 并返回其结果
  • orElseThrow(Supplier <?extended X> exceptionSupplier)值存在时返回值,否则抛出由 Supplier 提供的异常

orElse和orElseGet之间的区别在于,前者返回一个始终创建的字符串,而后者使用Supplier,只有在Optional为空时才执行。
如果Optional值是一个简单的字符串,两种差异很小。如果orElse的参数是一个复杂的对象,则带有Supplier的orElseGet更合适,因为可以确保仅在需要时创建对象。

Optional<ComplexObject> val = values.stream.findFirst() 
val.orElse(new ComplexObject());
val.orElseGet(() -> new ComplexObject())

下面显示了库中orElseGet的实现。

public T orElseGet(Supplier<? extends T> other) { 
    return value != null ? value : other.get();
}

orElseThrow方法也需要一个Supplier。在API中,方法签名为:

<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)

因此,在以下示例中,当Optional包含值时,不执行Supplier。


Optional<String> first =
    Stream.of("five", "even", "length", "string", "values")
    .filter(s -> s.length() % 2 == 0)
    .findFirst();
System.out.println(first.orElseThrow(NoSuchElementException::new));

最后,ifPresent方法允许我们提供一个Consumer,仅当Optional包含一个值时才执行。

Optional<String> first =
    Stream.of("five", "even", "length", "string", "values")
    .filter(s -> s.length() % 2 == 0) .findFirst();
first.ifPresent(val -> System.out.println("Found an even-length string"));
first = Stream.of("five", "even", "length", "string", "values") 
    .filter(s -> s.length() % 2 != 0)
    .findFirst();
first.ifPresent(val -> System.out.println("Found an odd-length string"));

在这种情况下,将仅打印消息“Found an odd-length string”。

评论

此博客中的热门博文

D3js Data-binding basics

JavaScript 数据类型

Vue3新特性(1) —— Vite