流转换是指从一个流中读取数据,并将转换后的数据写入到另一个流中。前面介绍过过滤器转换,它会产生一个新的流,其中包含符合某个特定条件的所有元素:
List<String> wordList = ......; Stream<String> words = wordList.stream(); Stream<String> longWords = words.filter(w -> w.length() > 12);
filter方法的参数是一个Predicate<T>对象——即一个从T到boolean的函数。
我们经常需要对一个流中的值进行某种形式的转换。这时可以考虑使用map方法,并传递给它一个执行转换的函数。例如:
package java8test; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class T1 { public static void main(String[] args) { List<String> wordList = Arrays.asList("abc","mdw","ket"); Stream<String> words = wordList.stream(); //注意下面这一句 Stream<String> lowercaseWords = words.map(String::toUpperCase); lowercaseWords.forEach(System.out::println); } }
在上例中,我们使用了带有一个方法引用的map方法。通常,你会使用一个lambda表达式来代替方法表达式:
Stream<Character> firstChars = words.map(s -> s.charAt(0));
该方法产生的流会包含每个单词的第一个字符。
当你使用map方法时,会对每个元素应用一个函数,并将返回的值收集到一个新的流中。现在,假设你有一个函数,它返回的不是一个值,而是一个包含多个值的流,如下所示:
package java8test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class T1 { public static void main(String[] args) { List<String> wordList = Arrays.asList("abc","mdw","ket"); Stream<String> words = wordList.stream(); //注意下面两句 Stream<Stream<Character>> lowercaseWords = words.map(T1::characterStream); lowercaseWords.forEach(stream -> stream.forEach(System.out::println)); } public static Stream<Character> characterStream(String s) { List<Character> result = new ArrayList<>(); //Stream<T>,T必须是类类型,基本类型不可以 for(char c:s.toCharArray()) result.add(Character.valueOf(c)); return result.stream(); } }
上例,如果我们使用常用的map()方法获取的lowercaseWords数据结构为:[['a','b','c'],['m','d','w'],['k','e','t']]。如果我们要得到如:['a','b','c','m','d','w','k','e','t']这样数据结构的数据,就需要使用flatMap()方法。示例:
package java8test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class T1 { public static void main(String[] args) { List<String> wordList = Arrays.asList("abc","mdw","ket"); Stream<String> words = wordList.stream(); //再次注意下面两句 Stream<Character> lowercaseWords = words.flatMap(T1::characterStream); lowercaseWords.forEach(System.out::println); } public static Stream<Character> characterStream(String s) { List<Character> result = new ArrayList<>(); for(char c:s.toCharArray()) result.add(Character.valueOf(c)); return result.stream(); } }