1. 获取Stream流

1.1 单列集合

List<String> list = new ArrayList<String>();  
Collections.addAll(list, "a", "b", "c", "d");  
list.stream().forEach(str -> System.out.print(str + "\t"));  
  
Set<String> set = new HashSet<String>();  
Collections.addAll(set, "a", "b", "c", "d");  
set.stream().forEach(str -> System.out.print(str + "\t"));

1.2 双列集合

Map<String,Integer> map = new HashMap<String, Integer>();  
map.put("a", 1);  
map.put("b", 2);  
map.put("c", 3);  

map.keySet().stream().forEach(k -> System.out.print(k + "\t"));  
System.out.println("\n");  

map.values().stream().forEach(v -> System.out.print(v + "\t"));  
System.out.println("\n");  

map.entrySet().stream().forEach(entry -> System.out.print(entry + "\t"));  
System.out.println("\n");

1.3 数组

String[] strArray = {"hello","world","java"};  
Arrays.stream(strArray).forEach(str -> System.out.print(str + "\t"));  
System.out.println("\n");

1.4 其他

Stream<String> stream1 = Stream.of("hello", "world", "java");  
Stream<Integer> stream2 = Stream.of(10, 20, 30);

2. 中间方法

2.1 filter()

  • 按照一定的规则过滤流中的数据
ArrayList<String> list = new ArrayList<>();  
list.add("张三丰");  
list.add("张无忌");  
list.add("张翠山");  
list.add("王二麻子");  
list.add("张良");  
list.add("谢广坤");  
  
/*  
 * Stream<T> filter(Predicate predicate):过滤  
 * Predicate接口中的方法  boolean test(T t):  
 * 对给定的参数进行判断,返回一个布尔值  
 */
 list.stream().filter(new Predicate<String>() {  
    @Override  
    public boolean test(String s) {  
        return s.startsWith("张");  
    }  
}).forEach(System.out::println);  

// 简化
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);

2.2 limit() & skip()

  • limit(long n) 只保留流中前n个元素
  • skip(long n) 跳过流中的前n个元素
// 创建一个集合,存储多个字符串元素  
ArrayList<String> list = new ArrayList<String>();  
list.add("林青霞");  
list.add("张曼玉");  
list.add("王祖贤");  
list.add("柳岩");  
list.add("张敏");  
list.add("张无忌");  

// 取前3个数据在控制台输出  
list.stream().limit(3).forEach(System.out::println);
  
// 跳过3个元素,把剩下的元素在控制台输出  
list.stream().skip(3).forEach(System.out::println);  
  
// 跳过2个元素,把剩下的元素中前2个在控制台输出  
list.stream().skip(2).limit(2).forEach(System.out::println);

2.3 distinct()

  • 去除流中相同的元素
//创建一个集合,存储多个字符串元素  
ArrayList<String> list = new ArrayList<String>();  
list.add("林青霞");  
list.add("林青霞");  
list.add("林青霞");  
list.add("林青霞");  
list.add("张曼玉");  
list.add("王祖贤");  
list.add("柳岩");  
list.add("张敏");  
list.add("张无忌");  
  
// 去除重复的字符串  
list.stream().distinct().forEach(System.out::println);

2.4 map()

  • 将流中的元素转换成指定的类型
//创建一个集合,存储多个字符串元素  
ArrayList<String> list = new ArrayList<String>();  
  
list.add("林青霞-10");  
list.add("张曼玉-15");  
list.add("王祖贤-90");  
list.add("柳岩-20");  
list.add("张敏-46");  
list.add("张无忌-18");  
  
// 转换并打印数字  
list.stream().map(new Function<String, Integer>() {  
    @Override  
    public Integer apply(String s) {  
        String numStr = s.split("-")[1];  
        return Integer.valueOf(numStr);  
    }  
}).forEach(System.out::println);  
  
// 精简的写法  
list.stream()  
        .map(s -> Integer.valueOf(s.split("-")[1]))  
        .forEach(System.out::println);

2.5 Stream.concat()

  • 合并两个流
//创建一个集合,存储多个字符串元素  
ArrayList<String> list = new ArrayList<String>();  
list.add("林青霞");  
list.add("张曼玉");  
list.add("王祖贤");  
list.add("柳岩");  
list.add("张敏");  
list.add("张无忌");  
  
//需求1:取前4个数据组成一个流  
Stream<String> s1 = list.stream().limit(4);  
  
//需求2:跳过4个数据组成一个流  
Stream<String> s2 = list.stream().skip(4);  
  
//需求3:合并需求1和需求2得到的流,并把结果在控制台输出  
Stream.concat(s1, s2).forEach(System.out::println);  
  
//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复  
Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));

3. 终结方法

3.1 forEach()

ArrayList<String> list = new ArrayList<>();  
list.add("张三丰");  
list.add("张无忌");  
list.add("张翠山");  
list.add("王二麻子");  
list.add("张良");  
list.add("谢广坤");  
  
// void forEach(Consumer action) 对此流的每个元素执行操作  
list.stream().forEach(new Consumer<String>() {  
    @Override  
    public void accept(String s) {  
        System.out.println(s);  
    }  
});  
  
// 简化  
list.stream().forEach(System.out::println);

3.2 toArray()

ArrayList<String> list = new ArrayList<>();  
list.add("张三丰");  
list.add("张无忌");  
list.add("张翠山");  
list.add("王二麻子");  
list.add("张良");  
list.add("谢广坤");  
  
// Object[] toArray() 返回流生成的数组  
Object[] array1 = list.stream().toArray();  
System.out.println(Arrays.toString(array1));  
  
// <A> A[] toArray(IntFunction<A[]> generator) 返回流生成的指定类型的数组  
/*  
* 1. IntFunction的泛型是要返回的具体类型  
* 2. apply的形参是流中数据的个数,要跟数组的长度保持一致  
* 3. apply的返回值是具体类型的数组  
* */  
String[] array2 = list.stream().toArray(new IntFunction<String[]>() {  
    @Override  
    public String[] apply(int value) {  
        return new String[value];  
    }  
});  
System.out.println(Arrays.toString(array2));  
  
// 简化  
/*  
* 1. toArray方法的参数的作用:负责创建一个指定类型的数组  
* 2. toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组中  
* 3. toArray方法的返回值:是一个装着流里面所有数据的数组  
* */  
String[] array3 = list.stream().toArray(num -> new String[num]);  
System.out.println(Arrays.toString(array3));

3.3 collect()

ArrayList<String> list = new ArrayList<>();  
list.add("小明-男-18");  
list.add("小明-男-18");  
list.add("小红-女-31");  
list.add("小王-男-12");  
list.add("小李-女-64");  
list.add("小张-男-32");  
list.add("小强-男-55");  
list.add("小刚-女-21");  
  
// 获取list中性别为男的元素,并转成一个新的list集合  
List<String> newList1 = list.stream().filter(s -> "男".equals(s.split("-")[1])).toList();  
List<String> newList2 = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList());  
System.out.println(newList1);  
System.out.println(newList2);  
  
// 获取list中性别为男的元素,并转成一个新的set集合  
Set<String> newSet = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet());  
System.out.println(newSet);  
  
// 将数据转成map的格式,使用名字作为key,年龄作为value  
Map<String, Integer> newMap1 = list.stream().distinct().collect(Collectors.toMap(  
        new Function<String, String>() {  
            @Override  
            public String apply(String s) {  
                return s.split("-")[0];  
            }  
        },  
        new Function<String, Integer>() {  
            @Override  
            public Integer apply(String s) {  
                return Integer.parseInt(s.split("-")[2]);  
            }  
        }  
));  
// 简化  
Map<String, Integer> newMap2 = list.stream()  
        .distinct()  
        .collect(  
                Collectors.toMap(  
                        s -> s.split("-")[0],  
                        s -> Integer.parseInt(s.split("-")[2]))  
        );  
System.out.println(newMap1);  
System.out.println(newMap2);

3.4 count()

ArrayList<String> list = new ArrayList<>();  
list.add("张三丰");  
list.add("张无忌");  
list.add("张翠山");  
list.add("王二麻子");  
list.add("张良");  
list.add("谢广坤");  
  
// long count() 返回此流中的元素数  
System.out.println(list.stream().count());

4. 练习

1. 练习1

/*  
* 1. 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10  
* 过滤奇数,只保留偶数,并将结果保存为数组  
* */  
  
public static void main(String[] args) {  
    List<Integer> nums = new ArrayList<>();  
    Collections.addAll(nums, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
  
    Integer[] array = nums.stream().filter(num -> num % 2 == 0).toArray(Integer[]::new);  
    System.out.println(Arrays.toString(array));  
}

2. 练习2

/*  
* 2. 创建一个ArrayList集合,并添加一下字符串,字符串前面是姓名,后面是年龄  
* “zhangsan”, 23  
* "lisi", 45  
* "wangwu", 25  
* 保留年龄大于等于24的人,并将结果收集到Map集合中,姓名为键,年龄为值  
* */  
public static void main(String[] args) {  
    ArrayList<String> list = new ArrayList<>();  
    Collections.addAll(list, "zhangsan,23", "lisi,45", "wangwu,37");  
  
    Map<String, Integer> collect = list.stream()  
            .filter(s -> Integer.parseInt(s.split(",")[1]) >= 24)  
            .collect(  
                    Collectors.toMap(  
                            s -> s.split(",")[0],  
                            s -> Integer.parseInt(s.split(",")[1])  
                    )  
            );  
    System.out.println(collect);  
}

3. 练习3

/*  
* 3. 现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作  
*       男演员只要名字为3个字的前三人  
*       女演员只要姓林的,并且不要第一个  
*       把过滤后的男演员姓名和女演员姓名合并到一起  
*       把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据  
*       演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法  
* */    
public static void main(String[] args) {  
    //创建集合  
    ArrayList<String> manList = new ArrayList<String>();  
    manList.add("周润发");  
    manList.add("成龙");  
    manList.add("刘德华");  
    manList.add("吴京");  
    manList.add("周星驰");  
    manList.add("李连杰");  

    ArrayList<String> womanList = new ArrayList<String>();  
    womanList.add("林心如");  
    womanList.add("张曼玉");  
    womanList.add("林青霞");  
    womanList.add("柳岩");  
    womanList.add("林志玲");  
    womanList.add("王祖贤");  

    Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);  
    Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);  
  
    Stream.concat(manStream, womanStream)  
        .map(s -> new Actor(s))  
        .forEach(actor -> System.out.println(actor));  
}  
  
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;  
    }  
  
    @Override  
    public String toString() {  
        return "Actor{" +  
                "name='" + name + '\'' +  
                '}';  
}