简短的定义:从支持数据处理操作的源生成的元素序列
剖析这个定义
元素序列:像集合一样,流也提供了一个接口,可以访问特定元素类型的一组有序值,因为集合是数据结构,所以他的主要目的是以特定的时间/空间复杂度存储和访问元素,但流的目的在于表达计算。集合讲的是数据,流讲的是计算。
源:流会使用一个提供数据的源,如集合、数组或输入/输出资源。请注意,从有序集合生成流时会保留原有的顺序。由列表生成的流,其元素序列与列表一致。
数据处理操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如filter、map、reduce、find、match、sort等。流操作可以顺序执行也可以并发执行。 流水线:很多流操作本身会返回一个流,这样多个操作就可以链接起来,形成一个流水线。
内部迭代:与使用迭代器显示迭代的集合不同,流的迭代操作是在背后进行的。
1)过滤筛选:filter
stream 接口支持filter方法,该操作接收一个谓词Predicate(一个返回bollean的函数)作为参数,并返回一个所有符合谓词元素的流。
2)排序:sort
3)去重:distinct
4)映射:map
map方法,它会接收一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素。
5)查找匹配:anyMatch、allMatch、noneMatch、findFirst、findAny
anyMatch:流中是否有一个元素能匹配给定的谓词。
allMath:流中所有元素是否能匹配给定的谓词。
noneMath:可以确保流中没有任何元素与给定的谓词匹配。
findAny:返回当前流中的任意元素。
findFirst:返回流中的第一个元素。
findAny 和 findFirst 有什么区别?
答案是并行,找到一个元素在并行上限制有很多,如果不关心返回的那个元素,请使用findAny,因为它在使用并行流时限制很少。
6)归约和汇总:reduce、groupingBy
reduce:接收两个参数,归约函数
1)一个初始值,
2)一个 BinaryOperator<T> 来将两个元素结合起来产生一个新值,
求和用lambda (a,b) ->a+b
求积用lambda (a,b) ->a*b
groupingBy:对流按照元素进行分组
Map<Currency,List<Transaction>> transactionByCurrencies =
transactions.stream().collect(groupingBy(Transaction::getCurrency));
7)截短流
流支持limit(n),该方法返回一个不超过给定长度的流,所需长度作为常数传递给limit。如果流是有序的,则最多返回前n个元素。请注意,limit也可以用在无序流上,比如源是一个set,这种情况,limit的结果不会以任何顺序排列。
8)跳过元素
流支持ship(n)方法,返回一个扔掉前n个元素的流,如果流中元素不足n个,怎返回一个空流,注意 limit 和 ship 是互补的。
9)流的扁平化(稍后会有专门的一篇文章来讲解流的扁平化)
flatMap方法,可以将生成的单个流合并起来,即扁平化一个流。
class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
代码如下:
List<User> users = Arrays.asList(new User(1, "Tomcat"), new User(2, "Apache"), new User(3, "Nginx"));
Map<Integer, User> map = users.stream().collect(Collectors.toMap(obj -> obj.getId() , obj -> obj));
System.out.println(map);
或者使用方法的引用
Map<Integer, User> map = users.stream().collect(Collectors.toMap(User::getId , obj -> obj));
最后,输出结果
{1=User [id=1, name=Tomcat], 2=User [id=2, name=Apache], 3=User [id=3, name=Nginx]}
有如下List<Map<String, String>>
List<Map<String, String>> list = new ArrayList<>();
Map<String, String> map1 = new HashMap<>();
map1.put("id", "101");
map1.put("name", "Tomcat");
Map<String, String> map2 = new HashMap<>();
map2.put("id", "102");
map2.put("name", "Apache");
Map<String, String> map3 = new HashMap<>();
map3.put("id", "103");
map3.put("name", "Nginx");
list.add(map1);
list.add(map2);
list.add(map3);
参考代码如下:
List<String> ids = list.stream().map(entity -> entity.get("id")).collect(Collectors.toList());
System.out.println(ids);
或者
List<Object> ids = Arrays.asList(list.stream().map(entity -> entity.get("id")).toArray());
输出结果:
[101, 102, 103]
参考代码:
String queryString = "type=1&from=APP&source=homePage";
Map<String, String> map = Stream.of(queryString.split("&")).map(obj -> obj.split("=")).collect(Collectors.toMap(entry -> entry[0], entry -> entry[1]));
System.out.println(map);
输出结果:
{from=APP, source=homePage, type=1}
List<String> strs = Arrays.asList("1","2","3");
List<Integer> ints = strs.stream().map(obj -> Integer.valueOf(obj)).collect(Collectors.toList());
1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
2)交易员都在哪些不同城市工作过
3)查找所有来自于剑桥的交易员,并且按照姓名排序
4)返回所有交易员的姓名字符串,按字母排序
5)有没有交易员是在米兰工作过?
6)打印生活在剑桥的交易员所有交易额。
7)所有交易中,最高的交易额是多少?
8)找到交易额的最小的交易。
实体类创建:
//交易员
public class Trader {
private final String name;
private final String city;
public Trader(String n, String c) {
this.name = n;
this.city = c;
}
public String getCity() {
return city;
}
public String getName() {
return name;
}
public String toString(){
return "{"+"Trader:"+this.name+"in " + this.city;
}
}
实体类创建:
//交易信息类
public class Transaction {
private final Trader trader;
private final int year;
private final int value;
public Transaction(Trader trader, int year, int value){
this.value = value;
this.year = year;
this.trader = trader;
}
public Trader getTrader(){
return this.trader;
}
public int getValue() {
return value;
}
public int getYear() {
return year;
}
public String toString(){
return "{"+this.trader+","+"year:"+this.year+","+"value:"+this.value+"}";
}
}
八种查询实现
/*测试用例:执行交易的交易员。你的经理让你为八个查询找到答案
1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
2)交易员都在哪些不同城市工作过
3)查找所有来自于剑桥的交易员,并且按照姓名排序
4)返回所有交易员的姓名字符串,按字母排序
5)有没有交易员是在米兰工作过?
6)打印生活在剑桥的交易员所有交易额。
7)所有交易中,最高的交易额是多少?
8)找到交易额的最小的交易。
* */
public class learnStream {
public static void main(String arg[]){
Trader raoul = new Trader("Raoul","Cambridge");
Trader mario = new Trader("Mario","Milan");
Trader alan = new Trader("Alan","Cambridge");
Trader brian = new Trader("Brian","Cambridge");
List<Transaction> transactions = Arrays.asList(
new Transaction(brian,2011,300),
new Transaction(raoul,2012,1000),
new Transaction(raoul,2011,400),
new Transaction(mario,2012,710),
new Transaction(mario,2012,700),
new Transaction(alan,2012,950)
);
//1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
List<Transaction> tr2011 = transactions.stream()
.filter(transaction ->transaction.getYear() == 2011)
.sorted(Comparator.comparing(Transaction::getValue))
.collect(toList());
//2)交易员都在哪些不同城市工作过
List<String> cities = transactions.stream()
.map(transaction -> transaction.getTrader().getCity())
.distinct()
.collect(toList());
//3)查找所有来自于剑桥的交易员,并且按照姓名排序
List<Trader> name = transactions.stream()
.map(transaction -> transaction.getTrader())
.filter(trader -> trader.getCity().equals("Cambridge"))
.distinct()
.sorted(Comparator.comparing(Trader::getName))
.collect(toList());
//4)返回所有交易员的姓名字符串,按字母排序
String traderStr = transactions.stream()
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted()
.reduce("",(n1,n2) -> n1+n2);
String traderStr2 = transactions.stream()
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted()
.collect(joining());
//5)有没有交易员是在米兰工作过?
boolean mailanBased = transactions.stream()
.anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan"));
//6)打印生活在剑桥的交易员所有交易额。
transactions.stream()
.filter(transaction -> transaction.getTrader().getCity().equals("Cambridge"))
.map(Transaction::getValue)
.forEach(System.out::println);
//7)所有交易中,最高的交易额是多少?
Optional<Integer> highestValue = transactions.stream()
.map(transaction -> transaction.getValue())
.reduce(Integer::max);
//8)找到交易额的最小的交易。
Optional<Transaction> smallestTransaction = transactions.stream()
.min(Comparator.comparing(Transaction::getValue));
}
}
一、将数据收集进一个列表(Stream 转换为 List,允许重复值,有顺序)
//1.将数据收集进一个列表(Stream 转换为 List,允许重复值,有顺序)
//创建流
Stream<String> language = Stream.of("java", "python", "C++","php","java");
List<String> listResult = language.collect(Collectors.toList());
result.forEach(System.out::println);
//2.stream()代替流
List<String> list = Arrays.asList("java", "python", "C++","php","java");
List<String> listResult = list.stream().collect(Collectors.toList());
listResult.forEach(System.out::println);
输出结果为:
二、将数据收集进一个集合(Stream 转换为 Set,不允许重复值,没有顺序)
//1.将数据收集进一个集合(Stream 转换为 Set,不允许重复值,没有顺序)
Stream<String> language = Stream.of("java", "python", "C++","php","java");
Set<String> setResult = language.collect(Collectors.toSet());
setResult.forEach(System.out::println);
输出结果为:
三、用自定义的实现Collection的数据结构收集
List<String> list = Arrays.asList("java", "python", "C++","php","java");
//用LinkedList收集
List<String> linkedListResult = list.stream().collect(Collectors.toCollection(LinkedList::new));
linkedListResult.forEach(System.out::println);
System.out.println("--------------");
//用CopyOnWriteArrayList收集
List<String> copyOnWriteArrayListResult = list.stream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));
copyOnWriteArrayListResult.forEach(System.out::println);
System.out.println("--------------");
//用TreeSet收集
TreeSet<String> treeSetResult = list.stream().collect(Collectors.toCollection(TreeSet::new));
treeSetResult.forEach(System.out::println);
输出结果为:
四、对Stream的字符串拼接
List<String> list = Arrays.asList("java", "python", "C++","php","java");
//直接将输出结果拼接
System.out.println(list.stream().collect(Collectors.joining()));
//每个输出结果之间加拼接符号“|”
System.out.println(list.stream().collect(Collectors.joining(" | ")));
//输出结果开始头为Start--,结尾为--End,中间用拼接符号“||”
System.out.println(list.stream().collect(Collectors.joining(" || ", "Start--", "--End")));
输出结果为:
五、其他还有partitioningBy(),分类成一个key为True和Flase的Map。
例如
List<String> list = Arrays.asList("java", "python", "C++","php","java");
Map<Boolean, List<String>> result = list.stream().collect(partitioningBy(s -> s.length() > 2));
六、collectingAndThen(),收集之后继续做一些处理。
例如
List<String> list = Arrays.asList("java", "python", "C++","php","java");
//收集后转换为不可变List
ImmutableList<String> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf));
总结:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。