Runnable noAtguments = () -> System.out.println("Hello,World"); ActionListener oneArgument = event -> System.out.println("button clicked"); Runnable multiStatement = () -> { System.out.println("Hello,"); System.out.println(" world"); } BinaryOperator<Long> add = (x,y) -> x + y; BinaryOperator<Long> addExplicit = (Long x,Long y) -> x + y;
接口 | 参数 | 返回类型 | 示例 |
---|---|---|---|
Predicate |
T | boolean | 这张唱片已经发行了吗 |
Consumer |
T | void | 输出一个值 |
Function |
T | R | 获得Artist对象的名字 |
Supplier |
None | T | 工厂方法 |
UnaryOperator |
T | T | 逻辑非(!) |
BinaryOperator |
(T,T) | T | 求两个数的乘积 |
指定泛型的类型
Map<String,Integer> oldWordCounts = new HashMap<String, Integer>(); Map<String,Integer> oldWordCounts = new HashMap<>();
useHashMap(new HashMap<>()); ... private void useHashMap(Map<String,String> values);
predicate接口源码,接受一个对象,返回一个布尔值
public interface Predicate<T>{ boolean test(T t); }
使用for循环计算来自伦敦的艺术家人数
int count = 0; for(Artist artist : allArtist){ if(artist.isFrom("London")){ count++; } }
使用迭代器计算来自伦敦艺术家人数
int count = 0; Iterator<Artist> iterator = allArtist.iterator(); while(iterator.hasNext()){ Artist artist = iterator.next(); if(artist.isFrom("London")){ count++; } }
使用内部迭代器计算来自伦敦艺术家人数
Long count = allArtist.stream() .filter(artist -> artist.isFrom("London")) .count();
filter只是刻画出Stream,但没有产生新的集合,这种叫做惰性求值方法
count这种从Stream中产生值的方法叫做及早求值方法
区分就看返回值,返回值是Stream,就是惰性求值
返回值若是另一个值或者为空,就是及早求值
整个过程和建造者模式有共通之处,建造者模式使用一系列操作设置属性和配置,最后调用一个build方法,这时对象才被真正创建
collect(toList())方法由Stream里的值生成一个列表,是一个及早求值操作
List<String> collected = Stream.of("a","b","c") .collect(Collectors.toList()); assertEquals(Arrays.asList("a","b","c"),collected); //断言判断结果是否一致
map操作就可以将一个流中的值转换成一个新的流
正常使用for循环将字符串全部改成大写
List<String> collected = new ArrayList<>(); for(String string:asList("a","b","hello")){ String uppercaseString = string.toUpperCase(); collected.add(uppercaseString); } assertEquals(asList("A","B","HELLO"), collected);
使用map操作将字符串转换为大写形式
List<String> collected = Stream.of("a","b","hello") .map(string -> string.toUpperCase()) .collect(collectors.toList()); assertEquals(asList("A","B","HELLO"), collected);
传给map的Lambda表达式只接受一个String类型的参数,返回一个新的String。参数和返回值不必属于同一种类型,但是Lambda表达式必须是Function接口的一个实例,Function接口是只包含一个参数的普通函数接口
该函数的接口是Function
I -> Function ->R
filter遍历数据并检查其中的元素时
使用循环遍历列表,使用条件语句做判断
List<String> beginningWithNumbers = new ArrayList<>(); for(String value : asList("a","1abc","abc1")){ if(isDigit0(value.get(0))){ beginningWithNumbers.add(value); } } assertEquals(asList("1abc"),beginningWithNumbers);
函数式风格
List<String> beginningWithNumbers = Stream.of("a","1abc","abc1") .filter(value -> isDigit(value.charAt(0))) .collect(toList()); assertEquals(asList("1abc"),beginningWithNumbers);
该函数的接口Predicate
I -> Predicate ->boolean
flatMap方法可用Stream替换值,然后将多个Stream连接成一个Stream
包含多个列表的Stream
List<Integer> together = Stream.of(asList(1,2),asList(3,4)) .flatMap(number -> numbers.stream()) .collect(toList()); assertEquals(asList(1,2,3,4), together);
调用stream方法,将每个列表转换成Stream对象,其余部分有flatMap方法处理。flatMap方法的相关函数接口和map方法一样都是Function接口,只是方法的返回值限定为Stream类型罢了
Stream上常用的操作就是求最值
使用Stream查找最短曲目
List<Track> tracks = asList(new Track("Bakai",524), new Track("Violets",378), new Track("Time was",451)); Track shorttestTrack = tracks.stream() .min(Comparator.comparing(track -> track.getLength())) .get() assertEquals(tracks.get(1),shorttestTrack);
使用reduce操作实现累加
Lambda表达式就是reducer,他执行求和操作,有两个参数:传入Stream中的当前元素和acc,将两个参数相加,acc就是累加器,保存当前的累加的结果
int count = Stream.of(1,2,3) .reduce(0,(acc,element) -> acc + element); assertEquals(6,count); //展开操作就是 BinaryOperator<Integer> accumulator = (acc, elelemnt) -> acc + element; int count = accumulator.apply( accumulator.apply( accumulator.apply(0,1), 2), 3); //使用命令式编程方式求和 int acc = 0; for(Integer element : asList(1,2,3)){ acc = acc + element; } assertEquals(6,acc);
找出某张专辑上所有乐队的国籍
Set<String> orgins = album.getMusicians() .filter(artist -> artist.getName().startsWith("The")) .map(artist -> artist.getNationality()) .collect(toSet());