lambda ::表达式
这篇博客文章包含基本Lambda表达式和Stream API示例的列表,我在2014年6月在Java用户组Politechnica Gedanensis (格但斯克技术大学)和Goyello的实时编码演示中使用了这些示例。
Lambda表达式
句法
最常见的示例:
Runnable runnable = () -> System.out.println("Hello!");
Thread t = new Thread(runnable);
t.start();
t.join();
可以这样写:
Thread t = new Thread(() -> System.out.println("Hello!"));
t.start();
t.join();
那参数呢?
Comparator<String> stringComparator = (s1, s2) -> s1.compareTo(s2);
并扩展为完整表达:
Comparator<String> stringComparator = (String s1, String s2) -> {
System.out.println("Comparing...");
return s1.compareTo(s2);
};
功能界面
Lambda表达式使您可以更紧凑地表达单方法类的实例。 单方法类称为函数接口, 可以使用@FunctionalInterface
进行注释:
@FunctionalInterface
public interface MyFunctionalInterface<T> {
boolean test(T t);
}
// Usage
MyFunctionalInterface<String> l = s -> s.startsWith("A");
方法参考
方法引用是紧凑的,易于阅读的lambda表达式,用于具有名称的方法。 让我们看一个简单的例子:
public class Sample {
public static void main(String[] args) {
Runnable runnable = Sample::run;
}
private static void run() {
System.out.println("Hello!");
}
}
另一个例子:
public static void main(String[] args) {
Sample sample = new Sample();
Comparator<String> stringLengthComparator = sample::compareLength;
}
private int compareLength(String s1, String s2) {
return s1.length() - s2.length();
}
流API –基础
流是支持顺序和并行批量操作的一系列元素。
遍历列表
List<String> list = Arrays.asList("one", "two", "three", "four", "five", "six");
list.stream()
.forEach(s -> System.out.println(s));
筛选
Java 8在接口中引入了默认方法。 它们在Stream API中非常方便:
Predicate<String> lowerThanOrEqualToFour = s -> s.length() <= 4;
Predicate<String> greaterThanOrEqualToThree = s -> s.length() >= 3;
list.stream()
.filter(lowerThanOrEqualToFour.and(greaterThanOrEqualToThree))
.forEach(s -> System.out.println(s));
排序
Predicate<String> lowerThanOrEqualToFour = s -> s.length() <= 4;
Predicate<String> greaterThanOrEqualToThree = s -> s.length() >= 3;
Comparator<String> byLastLetter = (s1, s2) -> s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1);
Comparator<String> byLength = (s1, s2) -> s1.length() - s2.length();
list.stream()
.filter(lowerThanOrEqualToFour.and(greaterThanOrEqualToThree))
.sorted(byLastLetter.thenComparing(byLength))
.forEach(s -> System.out.println(s));
另外,在上述例子的默认方法and
的java.util.function.Predicate
被使用。 默认(和静态)方法是Java 8中接口的新增方法。
限制
Predicate<String> lowerThanOrEqualToFour = s -> s.length() <= 4;
Predicate<String> greaterThanOrEqualToThree = s -> s.length() >= 3;
Comparator<String> byLastLetter = (s1, s2) -> s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1);
Comparator<String> byLength = (s1, s2) -> s1.length() - s2.length();
list.stream()
.filter(lowerThanOrEqualToFour.and(greaterThanOrEqualToThree))
.sorted(byLastLetter.thenComparing(byLength))
.limit(4)
.forEach(s -> System.out.println(s));
收集到清单
Predicate<String> lowerThanOrEqualToFour = s -> s.length() <= 4;
Predicate<String> greaterThanOrEqualToThree = s -> s.length() >= 3;
Comparator<String> byLastLetter = (s1, s2) -> s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1);
Comparator<String> byLength = (s1, s2) -> s1.length() - s2.length();
List<String> result = list.stream()
.filter(lowerThanOrEqualToFour.and(greaterThanOrEqualToThree))
.sorted(byLastLetter.thenComparing(byLength))
.limit(4)
.collect(Collectors.toList());
并行处理
我使用了一个非常常见的示例来遍历文件列表:
public static void main(String[] args) {
File[] files = new File("c:/windows").listFiles();
Stream.of(files)
.parallel()
.forEach(Sample::process);
}
private static void process(File file) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Processing -> " + file);
}
请注意,在显示示例时,我解释了并行处理流的一些已知缺点。
流API –更多示例
制图
遍历目录中的文件并返回FileSize
对象:
class FileSize {
private final File file;
private final Long size;
FileSize(File file, Long size) {
this.file = file;
this.size = size;
}
File getFile() {
return file;
}
Long getSize() {
return size;
}
String getName() {
return getFile().getName();
}
String getFirstLetter() {
return getName().substring(0, 1);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("file", file)
.add("size", size)
.toString();
}
}
映射的最终代码:
File[] files = new File("c:/windows").listFiles();
List<FileSize> result = Stream.of(files)
.map(FileSize::new)
.collect(Collectors.toList());
分组
按文件名的首字母对FileSize
对象进行分组:
Map<String, List<FileSize>> result = Stream.of(files)
.map(FileSize::new)
.collect(Collectors.groupingBy(FileSize::getFirstLetter));
减少
获取目录中最大/最小的文件:
Optional<FileSize> filesize = Stream.of(files)
.map(FileSize::new)
.reduce((fs1, fs2) -> fs1.getSize() > fs2.getSize() ? fs1 : fs2);
如果您不需要FileSize
对象,而只需要一个数字:
OptionalLong max = Stream.of(files)
.map(FileSize::new)
.mapToLong(fs -> fs.getSize())
.max();
翻译自: https://www.javacodegeeks.com/2014/06/lambda-expressions-and-stream-api-basic-examples.html
lambda ::表达式