新增了三个字符串函数,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 中获取值
- 获取链接
- X
- 电子邮件
- 其他应用
可以使用get方法获取Optinal中的值,但是,如果Optional为空,get方法将引发NoSuchElementException。
举个🌰:
Optional<String> firstEven =
Stream.of("five", "even", "length", "string", "values")
.filter(s -> s.length() % 2 == 0)
.findFirst();
findFirst方法返回Optional
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”。
- 获取链接
- X
- 电子邮件
- 其他应用
此博客中的热门博文
PHP8 —— Match Expressions
假设我们要保存发生的事件,根据时间的 class 来获取入库时的名称,PHP8 之前可以用 switch 实现 class Conversation {} $obj = new Conversation(); switch (get_class($obj)) { case 'Conversation': $type = 'started_conversation'; break; case 'Replay': $type = 'replied_to_conversation'; break; case 'Comment': $type = 'commented_on_lesson'; break; } echo $type; 显然这样写起来很繁琐。PHP8之后,可以使用 match expression 来改写,用键值对直接表达对应关系,省略了 case 、break等关键字。 $type = match(get_class($obj)) { 'Conversation' => 'started_conversation', 'Replay' => 'replied_to_conversation', 'Comment' => 'commented_on_lesson' } 当然,除了直接返回值之外,也能返回表达式;对相同返回的分支也可以做合并。比如使用match来实现一个请求路由。 $status = match($request_method) { 'post' => $this->handlePost(), 'get', 'head' => $this->handleGet(), default => throw new \Exception...
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) {...
Lambda structure
Function $$\lambda x.x$$ is a simple function. It has a head, which is a lambda ($\lambda$) followed by a variable name, and a body, and the head and body of the function is separated by a dot ($.$). When we applied this function to an argument, the x in the body will have the value of that given argument. Alpha equivalence $$\lambda x.x$$ $$\lambda y.y$$ $$\lambda z.z$$ all there three are the same thing. The letters here are not meaningful, just a way of expression. This equivalence is called alpha equivalence. Beta reduction Beta reduction is the process in which we apply a function to arguments, substitute the input expression for all bound variables in the body, and eliminate the head. If we apply $\lambda x.x$ to a number, for example 42, we can substitute 42 for each $x$ in the body, and eliminate the head: $$(\lambda x.x) 42$$ $$42$$ Another example: apply function $(\lambda x.x*4)$ to 8, we got $$(\lambda x.x*4) 8$$ $$8*4$$ $$32$$ We can apply function to another funct...
评论