Java的模式笔记

由于这是个人备忘录,所以可能会随意添加或被搁置。

List.of比Arrays.asList更好用。

在JDK9及以后的版本中,使用List.of比使用Arrays.asList更好。
Arrays.asList返回的List只是一个数组的包装器,大小固定但元素是可修改的。而List.of返回的List是不可修改的,元素也不能被修改。

n -> int[n]使用int[]::new

这个看起来有点神秘的句子,但就是这样的。
就像 new String(data) 可以写成 String::new 一样。

不使用FunctionalInterface的字段。

final Function<String, Price> CONVERT_STRING_TO_PRICE = 
  str -> str.substring(0, str.length() - 1).transfer(Price::of);

定义一个名为”というフィールド”的字段。

return inputs.stream()
  .map(CONVERT_STRING_TO_PRICE)
  .collect(toList());

有时候可以使用类似的方法。

然而,可以以常规方式定义一个方法。

Price stringToPrice(String str) {
  return str.substring(0, str.length() - 1).transfer(Price::of);
}

最好使用方法引用。

return inputs.stream()
  .map(Converters::stringToPrice)
  .collect(toList());

在Java中,可以正确地编写JavaDoc注释,而且方法比高阶函数更易读。此外,由于Lambda最终会编译成方法定义和方法引用,所以有点多余。

不使用Optional作为字段使用

由于不可序列化等原因,最好在普通值上附加@Nullable等注解来使用。

不要将Stream用作返回值。

除非是操作Stream自身的方法,否则最好不要将Stream作为返回值。
作为标准,可以返回Stream,但是返回具体类型如Stream的方法并不是很好。
或者像Files.lines一样,如果需要进行I/O并且想要进行”流处理”的情况下可以返回Stream。

流傾向

当我们想要对boolean[]或者char[]进行流处理时,可以使用IntStream。

举个例子,假设有字符chars。

char[] chars;

由于Arrays.stream没有接受char[]的方法,所以会产生错误。
使用Stream.of可以创建处理char数组本身的Stream。
因此,我们可以使用IntStream来生成索引,并同时进行mapToObject操作。

IntStream.range(0, chars.length)->mapToObject(i -> chars[i])

当需要一个int数组生成器时,可以使用IntStream.builder()。

var builder = IntStream.builder();
builder.add(2);
builder.add(5);
int[] result = builder.build().toArray();

任一匹配

for (var a : list) {
  if (condition(a)) {
    return true;
  }
}
return false

请提供更多上下文以根据您的要求进行重述。

return list.stream().anyMatch(this::condition);

匹配所有

for (var a : list) {
  if (!condition(a)) {
    return false;
  }
}
return true

请将以下内容用中文进行准确表达,只需提供一种选项:

return list.stream().allMatch(this::condition);

不匹配

for (var a : list) {
  if (condition(a)) {
    return false;
  }
}
return true

请将以下内容用中文同义词重新表达,只需要一种选项:

return list.stream().noneMatch(this::condition);

不需要将Optional放入Stream或List中。

由于Optional是一个只能包含0个或1个元素的特殊集合,所以不需要进一步包装Stream或List,可以通过Stream.of()或emptyList()来处理。

如果只需要一种选择,请将以下句子用中文进行释义:

正常情况和异常情况 hé

在正常情况下,使用”then”;在异常情况下,使用”else”。

if (cond) {
  proc
} else {
  error
}

然而,如果异常情况在一行中通过return/throw语句直接退出时,将异常情况放入if语句中以实现提前退出。

if (!cond) {
  throw error
}
proc

!(aa && bb) : 非(aa 且 bb)

避免用类似于!(aa && bb)的大括号表示并避免反转似乎更好一些。

if (!(hasValue && isValid)) {
  error
}

相对而言

if (!hasValue || !isValid) {
  error
}

如果是那样的话,就不需要将结果缓存到大脑中。
但是,如果带有else的话。

if (!hasValue || !isValid) {
  error
} else {
  proc
}

比起来

if (hasValue && isValid) {
  proc
} else {
  error
}

の方が反転する必要がない。

在这种情况下,遵循将正常情况放在then的方针。

而且,这种逻辑上的反转应该由IDE自动完成,所以最好不要手动处理。

以下这句话的中文表达方式:
枚举

当参数存在时,在lombok中使用@AllArgsConstructor和@Getter。
@Value不能用于枚举。

@AllArgsConstructor
@Getter
enum Hoge {
  A("a-desu"),
  B("b-dayo");

  private String message;
}

Integer.valueOf函数返回 Integer 对象。

Integer和Long的valueOf函数返回包装对象。
所以这样的代码是多余的。

int n = Integer.valueOf(str);

如果想要将其用作原始类型,可以使用parseInt。

int n = Integer.parseInt(str);

要将IOException转换为非检查异常,可以使用UncheckedIOException。

catch (IOException ex) {
  throw new UncheckedIOException(ex);
}

在使用package private进行测试时,请加上@VisibleForTesting

请给Guava的@VisibleForTesting加上注解。希望在JUnit中被使用。

@VisibleForTesting
String createId(String seed) {
}