1. Stream流
1.1. Stream流引入
Stream流完全不是I/O流,按照流水线处理方式来考虑代码中的思想。 JDK1.8 之后,我们拥有了Lambda表达式,让代码的中心偏向解决实际问题,直到重点,可以提高效率。 Stream流中使用了大量Lambda表达式,利用Lambda操作方式,提供开发效率
1.2 传统遍历方式和Stream类处理方式对比
import java. util. ArrayList;
public class Demo2 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "宫保鸡丁" ) ;
list. add ( "酱牛肉" ) ;
list. add ( "羊肉串" ) ;
list. add ( "烤羊排" ) ;
list. add ( "羊肉汤" ) ;
list. add ( "驴肉火烧" ) ;
ArrayList< String> list1 = new ArrayList < > ( ) ;
for ( String s : list) {
if ( s. contains ( "肉" ) ) {
list1. add ( s) ;
}
}
ArrayList< String> list2 = new ArrayList < > ( ) ;
for ( String s : list1) {
if ( 3 == s. length ( ) ) {
list2. add ( s) ;
}
}
for ( String s : list2) {
System. out. println ( s) ;
}
}
}
import java. util. ArrayList;
public class Demo2 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "宫保鸡丁" ) ;
list. add ( "酱牛肉" ) ;
list. add ( "羊肉串" ) ;
list. add ( "烤羊排" ) ;
list. add ( "羊肉汤" ) ;
list. add ( "驴肉火烧" ) ;
list. stream ( )
. filter ( s- > s. contains ( "肉" ) )
. filter ( s - > 3 == s. length ( ) )
. forEach ( s - > System. out. println ( s) ) ;
}
}
1.3 Stream流对应的思想
流水线: 原材料从头到尾只会占用一份空间,中间的过程中不会占用空间。最后生成一个结果。
Stream流有一些特征:
带有很多Stream流操作的方法, filter,limit,map,sorted,skip…这些方法大多是都会使用到函数式接口,有lambda表达式
整个Stream流模型操作过程中,只有执行到count,foreach这些方法,操作真正的执行中的模型,如果不存在结果导向,中间的所有操作是无效的,这里得益于Lambda表达式的延后性
Stream流是存在一定的管道性 Pipelining 流水线
1.4 获取Stream流
java.util.stream.Stream JDK1.8的新特征
所有的Collection集合都有对应的Stream();
可以通过Stream类中的static Stream of()获取 static Stream of(T… t); static Stream of(T t);
import java. util. *;
import java. util. stream. Stream;
public class Demo1 {
public static void main ( String[ ] args) {
List< String> list = new ArrayList < > ( ) ;
Stream< String> stream = list. stream ( ) ;
HashSet< String> set1 = new HashSet < > ( ) ;
Stream< String> stream1 = set1. stream ( ) ;
HashMap< String, String> map = new HashMap < > ( ) ;
Set< String> keySet = map. keySet ( ) ;
Stream< String> stream2 = keySet. stream ( ) ;
Collection< String> values = map. values ( ) ;
Stream< String> stream3 = values. stream ( ) ;
Set< Map. Entry< String, String> > entrySet = map. entrySet ( ) ;
Stream< Map. Entry< String, String> > stream4 = entrySet. stream ( ) ;
Stream< String> stringStream = Stream. of ( "酱牛肉" , "羊肉抓饭" , "羊肉汤" , "羊蝎子" ) ;
String[ ] arr = { "黄河大鲤鱼" , "方中山胡辣汤" , "萧记烩面" , "蔡记蒸饺" , "葛记焖饼" } ;
Stream< String> arrStream = Stream. of ( arr) ;
ArrayList< String> list1 = new ArrayList < > ( ) ;
Stream< ArrayList< String> > list11 = Stream. of ( list1) ;
}
}
1.5 Stream常用方法
延迟方法: 返回值类型依然是Stream接口本身,并没有影响我们操作真正的资源允许链式操作,
例如 filter(XXX).limit(XXX).sorted(XXX).
终结方法: 返回值类型不是Stream接口本身,要么处理数据,要么返回其他类型数据,并且不再支持Stream流对象链式操作,count,foreach
1.5.1 foreach方法【终结方法】
void foreach ( Consumer< ? super T> action) ;
import java. util. ArrayList;
import java. util. List;
import java. util. function. Consumer;
import java. util. stream. Stream;
public class Demo1 {
public static void main ( String[ ] args) {
List< String> list = new ArrayList < > ( ) ;
list. add ( "蛋炒饭" ) ;
list. add ( "虎皮青椒" ) ;
list. add ( "手撕包菜" ) ;
list. add ( "鲱鱼罐头" ) ;
Stream< String> stream = list. stream ( ) ;
stream. forEach ( new Consumer < String> ( ) {
@Override
public void accept ( String s) {
System. out. println ( s) ;
}
} ) ;
stream. forEach ( string - > System. out. println ( string) ) ;
stream. forEach ( System. out: : println) ;
}
}
1.5.2 filter方法
Stream< T> filter ( Predicate< ? super T> condition) ;
import java. util. ArrayList;
import java. util. stream. Stream;
public class Demo2 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "擀面皮" ) ;
list. add ( "肉夹馍" ) ;
list. add ( "冰峰" ) ;
list. add ( "水盆羊肉" ) ;
Stream< String> stringStream = list. stream ( ) . filter ( s - > s. length ( ) >= 3 ) ;
stringStream. forEach ( System. out: : println) ;
Stream< String> stringStream1 = stringStream. filter ( s - > 4 == s. length ( ) ) ;
stringStream1. forEach ( System. out: : println) ;
}
}
1.5.3 map方法
< R> Stream< R> map ( Function< ? super T, ? super R> fun) ;
import java. util. ArrayList;
import java. util. stream. Stream;
public class Demo3 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "1,骚磊,16" ) ;
list. add ( "2,骚杰,66" ) ;
list. add ( "3,老黑,46" ) ;
list. add ( "4,老付,36" ) ;
list. add ( "5,污云,56" ) ;
list. add ( "6,帅栋,26" ) ;
System. out. println ( list) ;
Stream< Person> personStream = list. stream ( ) . map ( s - > {
String[ ] split = s. split ( "," ) ;
Person person = new Person ( ) ;
person. setId ( Integer. parseInt ( split[ 0 ] ) ) ;
person. setName ( split[ 1 ] ) ;
person. setAge ( Integer. parseInt ( split[ 2 ] ) ) ;
return person;
} ) ;
personStream. forEach ( System. out: : println) ;
}
}
1.5.4 count方法【终结方法】
long count ( ) ;
import java. util. ArrayList;
public class Demo4 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "擀面皮" ) ;
list. add ( "肉夹馍" ) ;
list. add ( "冰峰" ) ;
list. add ( "水盆羊肉" ) ;
long count = list. stream ( ) . filter ( s - > s. length ( ) >= 3 ) . count ( ) ;
System. out. println ( count) ;
}
}
1.5.5 limit方法
Stream< T> limit ( long maxSize) ;
import java. util. ArrayList;
import java. util. stream. Stream;
public class Demo5 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "红旗" ) ;
list. add ( "领克" ) ;
list. add ( "吉利" ) ;
list. add ( "比亚迪" ) ;
list. add ( "长安" ) ;
list. add ( "五菱宏光" ) ;
Stream< String> stream = list. stream ( ) ;
stream. limit ( 5 ) . forEach ( System. out: : println) ;
}
}
1.5.6 skip方法
Stream< T> skip ( long n) ;
import java. util. ArrayList;
public class Demo6 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "陆巡" ) ;
list. add ( "高R" ) ;
list. add ( "RS7" ) ;
list. add ( "s4" ) ;
list. add ( "霸道" ) ;
list. add ( "道奇" ) ;
list. stream ( ) . skip ( 2 ) . forEach ( System. out: : println) ;
}
}
1.5.7 concat方法
static Stream< T> concat ( Stream< ? extends T > a, Stream< ? extends T > b)
import java. util. ArrayList;
import java. util. stream. Stream;
public class Demo7 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < > ( ) ;
list. add ( "红旗" ) ;
list. add ( "领克" ) ;
list. add ( "吉利" ) ;
list. add ( "比亚迪" ) ;
list. add ( "长安" ) ;
list. add ( "五菱宏光" ) ;
ArrayList< String> list1 = new ArrayList < > ( ) ;
list1. add ( "陆巡" ) ;
list1. add ( "高R" ) ;
list1. add ( "RS7" ) ;
list1. add ( "s4" ) ;
list1. add ( "霸道" ) ;
list1. add ( "道奇" ) ;
Stream< String> stream = list. stream ( ) ;
Stream< String> stream1 = list1. stream ( ) ;
Stream< String> concat = Stream. concat ( stream, stream1) ;
concat. forEach ( System. out: : println) ;
}
}
1.5.8 原始操作方式和Stream流方式对比
import java. util. ArrayList;
public class Demo8 {
public static void main ( String[ ] args) {
ArrayList< String> list1 = new ArrayList < > ( ) ;
list1. add ( "1,骚磊,15" ) ;
list1. add ( "2,骚杰,65" ) ;
list1. add ( "3,老黑,45" ) ;
list1. add ( "4,老付,56" ) ;
list1. add ( "5,污云,56" ) ;
list1. add ( "6,帅栋,26" ) ;
list1. add ( "7,帅栋,56" ) ;
list1. add ( "8,帅栋,25" ) ;
list1. add ( "9,帅栋,26" ) ;
list1. add ( "10,帅栋,26" ) ;
list1. add ( "11,帅栋,25" ) ;
list1. add ( "12,帅栋,56" ) ;
list1. add ( "13,帅栋,55" ) ;
ArrayList< String> list2 = new ArrayList < > ( ) ;
for ( String s : list1) {
if ( s. contains ( "5" ) ) {
list2. add ( s) ;
}
}
System. out. println ( list2) ;
ArrayList< String> list3 = new ArrayList < > ( ) ;
for ( int i = 3 ; i < list2. size ( ) ; i++ ) {
list3. add ( list2. get ( i) ) ;
}
System. out. println ( list3) ;
ArrayList< String> list4 = new ArrayList < > ( ) ;
for ( int i = 0 ; i < 5 ; i++ ) {
list4. add ( list3. get ( i) ) ;
}
ArrayList< String> list5 = new ArrayList < > ( ) ;
list5. add ( "1,骚磊,15" ) ;
list5. add ( "2,骚杰,65" ) ;
list5. add ( "3,老黑,45" ) ;
list5. add ( "4,老付,56" ) ;
list5. add ( "5,污云,56" ) ;
list4. addAll ( list5) ;
ArrayList< Person> list6 = new ArrayList < > ( ) ;
for ( String s : list4) {
String[ ] split = s. split ( "," ) ;
Person person = new Person ( ) ;
person. setId ( Integer. parseInt ( split[ 0 ] ) ) ;
person. setName ( split[ 1 ] ) ;
person. setAge ( Integer. parseInt ( split[ 2 ] ) ) ;
list6. add ( person) ;
}
for ( Person person : list6) {
System. out. println ( person) ;
}
}
}
import java. util. ArrayList;
import java. util. stream. Stream;
public class Demo9 {
public static void main ( String[ ] args) {
ArrayList< String> list1 = new ArrayList < > ( ) ;
list1. add ( "1,骚磊,15" ) ;
list1. add ( "2,骚杰,65" ) ;
list1. add ( "3,老黑,45" ) ;
list1. add ( "4,老付,56" ) ;
list1. add ( "5,污云,56" ) ;
list1. add ( "6,帅栋,26" ) ;
list1. add ( "7,帅栋,56" ) ;
list1. add ( "8,帅栋,25" ) ;
list1. add ( "9,帅栋,26" ) ;
list1. add ( "10,帅栋,26" ) ;
list1. add ( "11,帅栋,25" ) ;
list1. add ( "12,帅栋,56" ) ;
list1. add ( "13,帅栋,55" ) ;
ArrayList< String> list2 = new ArrayList < > ( ) ;
list2. add ( "1,骚磊,15" ) ;
list2. add ( "2,骚杰,65" ) ;
list2. add ( "3,老黑,45" ) ;
list2. add ( "4,老付,56" ) ;
list2. add ( "5,污云,56" ) ;
list2. add ( "6,帅栋,26" ) ;
list2. add ( "7,帅栋,56" ) ;
Stream< String> stream = list1. stream ( ) ;
Stream< String> limit = stream. filter ( s - > s. contains ( "5" ) ) .
skip ( 3 ) .
limit ( 5 ) ;
Stream. concat ( limit, list2. stream ( ) ) . map ( s - > {
String[ ] split = s. split ( "," ) ;
Person person = new Person ( ) ;
person. setId ( Integer. parseInt ( split[ 0 ] ) ) ;
person. setName ( split[ 1 ] ) ;
person. setAge ( Integer. parseInt ( split[ 2 ] ) ) ;
return person;
} ) . forEach ( System. out: : println) ;
}
}
总结 流思想让我们更加的直接,它在没有出结果之前,几乎是不会消耗资源的(之前的过滤、限制、映射等,都是在进行完count或foreach后才会真正的进行)