生成流的操作
通过数据源(集合、数组等)生成流
如,list.stream()
中间操作
一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用
如,filter(),其操作完成之后还是一个stream流
终结操作
一个流只能有一个终结操作,当这个操作执行后,流就被使用"光"了,无法再被操作。所以这必定是流的最后一个操作forEach()
forEach()
Stream流常见的生成方式有三种
Colletion体系的集合可以使用默认方法stream()生成流
default Stream
List list = new ArrayList<>();
Stream listStream = list.stream();Set set = new HashSet<>();
Stream setStream = set.stream();
Map体系的集合间接的生成流
Map map = new HashMap<>();// 这就是间接的获取键的stream流:map.keySet() 得到键的set集合,再通过键的set集合获取到流,Stream keyStream = map.keySet().stream();// 间接的获取值的stream流Stream valueStream = map.values().stream();// 键值对对象所对应的流Stream> entryStream = map.entrySet().stream();
数组可以通过Stream接口的静态方法of(T...values)生成流
String[] strArray = {"hello","world","java"};Stream strArrayStream = Stream.of(strArray);Stream strArrayStream2 = Stream.of("hello", "world", "java");Stream intStream = Stream.of(10, 20, 30);
Stream
Predicate接口中的方法 boolean test(T t) : 对给定的参数进行判断,返回一个布尔值
ArrayList list = new ArrayList<>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");// 需求:把list集合中以张开头的元素在控制台输出// filter()需要一个函数式接口,在这里我们可以写一个lambda表达式list.stream().filter( (String s) ->{return s.startsWith("张");} ).forEach(System.out::println);
其中我们的lambda表达式可以简写成下面的形式
list.stream().filter(s->s.startsWith("张")).forEach(System.out::println);
list.stream().filter(s->s.length()==3).forEach(System.out::println);
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(System.out::println);
Stream
Stream
list.stream().limit(3).forEach(System.out::println);
list.stream().skip(3).forEach(System.out::println);
list.stream().skip(2).limit(2).forEach(System.out::println);
static
Stream
Stream s1 = list.stream().limit(4);
Stream s2 = list.stream().skip(2);
Stream.concat(s1, s2).forEach(System.out::println);
Stream.concat(s1,s2).distinct().forEach(System.out::println);
Stream
Stream
ArrayList list = new ArrayList<>();list.add("linqingxia");list.add("zhangmanyu");list.add("wangzuxian");list.add("liuyan");list.add("zhangmin");list.add("zhangwuji");list.stream().sorted().forEach(System.out::println);
list.stream().sorted((s1,s2)->{int num = s1.length()-s2.length();int num2 = num ==0 ? s1.compareTo(s2) : num;return num2;}).forEach(System.out::println);
Function接口中的方法 R apply(T t)
IntStream map ToInt(ToIntFuction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果
IntStream:表示原始int流
ToIntUFunction接口中的方法 int applyAsInt(T value)
ArrayList list = new ArrayList<>();list.add("10");list.add("20");list.add("30");list.add("40");list.add("50");list.stream().map(s->Integer.parseInt(s)).forEach(System.out::println);
或者
list.stream().map(Integer::parseInt).forEach(System.out::println);
或者 mapToInt也可以
list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
结果:
IntStream也是一个接口,支持顺序和并行聚合操作的原始int值元素序列,其有个方法是 int sum() 返回流中元素的总和
注意:sum方法是IntStream接口中的,而Stream接口中是没有的
int sum = list.stream().mapToInt(Integer::parseInt).sum();System.out.println(sum);
void forEach(Consumer action):对此流的每个元素执行操作
Consumer接口中的方法 void accept(T t): 对给定的参数执行此操作
我们前面指定的就是再控制台输出我们的数据
long count():返回此流中元素数
ArrayList list = new ArrayList<>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");list.stream().forEach(System.out::println);
long count = list.stream().filter(s -> s.startsWith("张")).count();System.out.println(count);
public class Actor {private String name;public Actor(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
ArrayList manList = new ArrayList<>();manList.add("周润发");manList.add("成龙");manList.add("刘德华");manList.add("吴京");manList.add("周星驰");manList.add("李连杰");ArrayList womanList = new ArrayList<>();womanList.add("林心如");womanList.add("张曼玉");womanList.add("林青霞");womanList.add("柳岩");womanList.add("林志玲");womanList.add("王祖贤");
现在有两个ArrayList集合,分别存储6名男演员和6名女演员名称,要求完成如下的操作
男演员只要名字为3个字的前三人
Stream manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
女演员只要姓林的,并且不要第一个
Stream womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
把过滤后的男演员姓名和女演员姓名合并到一起
Stream stream = Stream.concat(manStream, womanStream);
把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
演员类Actor已经提供,里面有一个成员变量,一个带构造方法,以及成员变量对应的get/set方法
stream.map(Actor::new).forEach(System.out::println);
我们没有重写toString方法
stream.map(Actor::new).forEach( p-> System.out.println(p.getName()));
对数据使用stream流的方式操作完毕后,想把流中的数据收集到集合中
Stream流的收集方法
R collect(Collector collector)
其中Collector super T,A,R>是一个接口
Collectors是一个工具类,实现各种有用的还原操作的Collector,例如将元素累积到集合中,根据各种标准汇总元素等
工具类Collectors提供了具体的收集方式
public static
ArrayList list = new ArrayList<>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");// 需求1:得到名字为3个字的流Stream listStream = list.stream().filter(s -> s.length() == 3);// 需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历List names = listStream.collect(Collectors.toList());for(String name :names){System.out.println(name);}}
public static
Set set = new HashSet<>();set.add(10);set.add(20);set.add(30);set.add(33);set.add(35);
// 需求: 大于25Stream setStream = set.stream().filter(are -> are > 25);
// 需求:把使用Stream流操作完毕的数据收集到Set集合中并遍历Set ages = setStream.collect(Collectors.toSet());for(Integer age :ages)System.out.println(age);
public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中
String[] strArray = {"林青霞,30","张曼玉,35","王祖贤,33","柳岩,25"};
// 需求:得到字符串中年龄数据大于28的流Stream arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);// 需求:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作为键,年龄作为值Map map = arrayStream.collect(Collectors.toMap( s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1]) ) );Set keySet = map.keySet();for(String key: keySet){System.out.println(key+","+map.get(key));}