Java——Stream流

Java——Stream流

stream是数据渠道,用于操作数据源(集合、数组)所生产的元素序列。这一类操作称作局和操作,它的基本流程是:

​ 1、将原始数据或数组对象转换为stream流。

​ 2、对stream流中的元素进行一系列的过滤、查找等中间操作(Intermediate Operations),然后 仍返回一个Stream流对象

​ 3、对stream流进行统计、遍历、收集等终结操作(Terminal Operation)获取想要的结果。

Stream流有以下的特点:

  • stream是不能存储数据,只能对数据进行一些列流式的操作。
  • stream是惰性加载(延迟执行),一系列流式的操作会在要结果的时候一起执行。
  • 不会修改源数据。
  • 每次操作得到一个新的流,不能对同一个stream执行多次操作 ,因为源流操作过以后就被破坏了。

获取流的三种方式

1、所有的Collection集合都可以使用接口中的默认方法stream()获取Stream流对象。该方法来自StreamSupport类的静态方法。

2、Stream接口的of()静态方法可以获取基本类型和包装类数组、引用类型数组和单个元素的stream对象。of(T… values)方法为可变参数或of(T t)

3、Arrays数组工具类的stream()静态方法可以获取数组元素的stream流对象。


Stream的中间操作

1. 筛选和切片

1.1 filter

创建Card类,私有属性为字符串类的name、int类型的攻击力、int类型的血量。创建一个容器保存一些数据,对这些数据转换的stream流进行filter筛选。

public class Demo02 {
	static List<Card> list = Arrays.asList(
			//名称、攻击、血量
        	new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//filter接收Lambda,排除流中攻击力小于8的卡牌
		Stream<Card> stream = list.stream().filter((e)->{
			return e.getAttack()>=8;
		});
		
		//对流进行终结操作
		stream.forEach(System.out::println);
	}	
}
//运行结果:
Card [name=红龙女王阿莱克斯塔萨, attack=8, blood=8]
Card [name=死亡之翼, attack=12, blood=12]
Card [name=巫妖王, attack=8, blood=8]

1.2 limit

public class Demo03 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//limit-截断流,使其元素不超过给定数量
		//排除流中攻击力小于3的卡牌,限制为3个
		list.stream().filter((e)->{
			return e.getAttack()>=3;
		}).limit(3).forEach(System.out::println);

	}	
}
//运行结果:
Card [name=红龙女王阿莱克斯塔萨, attack=8, blood=8]
Card [name=死亡之翼, attack=12, blood=12]
Card [name=巫妖王, attack=8, blood=8]

1.3 skip

public class Demo04 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//skip-跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流。
		list.stream().filter((e)->{
			return e.getAttack()>=2;
		}).skip(2).forEach(System.out::println);
	}	
}
//运行结果:
Card [name=死亡之翼, attack=12, blood=12]
Card [name=转校生, attack=2, blood=2]
Card [name=巫妖王, attack=8, blood=8]

1.4 distinct

public class Demo05 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		// distinct-筛选,通过流所生产元素的hashCode()和equals()去除重复元素
		Arrays.stream(list.toArray()).distinct().forEach(System.out::println);
	}	
}

2. 排序

2.1 sorted(Comparable)-自然排序

​ 自定义类需要实现Comparable接口,重写compareTo方法。按照名字长度升序排序。

public class Demo06 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
   		//自然排序实现名字升序排序
        list.stream().sorted().forEach(System.out::println);
	}	
}
//运行结果:
Card [name=小精灵, attack=1, blood=1]
Card [name=转校生, attack=2, blood=2]
Card [name=巫妖王, attack=8, blood=8]
Card [name=死亡之翼, attack=12, blood=12]
Card [name=魔古山守望者, attack=1, blood=7]
Card [name=了不起的杰弗里斯, attack=3, blood=2]
Card [name=红龙女王阿莱克斯塔萨, attack=8, blood=8]

2.2 sorted(Comparator)-定制排序

public class Demo07 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//自定义比较器,攻击力降序排序,攻击相同按血量降序
		list.stream().sorted((e1,e2)->{
			if(e1.getAttack() == e2.getAttack()) {
				return e2.getBlood()-e1.getBlood();
			}
			return e2.getAttack()-e1.getAttack();
			})
			.forEach(System.out::println);
    }
}
//运行结果:
Card [name=死亡之翼, attack=12, blood=12]
Card [name=红龙女王阿莱克斯塔萨, attack=8, blood=8]
Card [name=巫妖王, attack=8, blood=8]
Card [name=了不起的杰弗里斯, attack=3, blood=2]
Card [name=转校生, attack=2, blood=2]
Card [name=魔古山守望者, attack=1, blood=7]
Card [name=小精灵, attack=1, blood=1]

3. map映射操作

map(Function<? super T,? extends R> mapper)) 。把流中的数据,当做apply(T t) 方法参数传递,经过运算,最终返回一个结果,map方法调用后会返回一个包含着新结果的流。flatMap()会把多个流合并成一个流。

public class Demo08 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//将stream流里的对象的name映射为新的流输出
		list.stream().map((e)->{return e.getName();}).forEach((o)->System.out.println(o));;
	}	
}

终止操作

1. 查找与匹配

public class Demo09 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//allMatch-检查流内数据血量是否都满足条件大于1
		boolean b1 = list.stream().allMatch(a->a.getBlood()>1);
		System.out.println(b1);
		
		//anyMatch-检查是否至少匹配一个元素,攻击力大于10
		boolean b2 = list.stream().anyMatch(a->a.getAttack()>10);
		System.out.println(b2);
		
		//noneMatch-检查是否没有匹配所有元素
		boolean b3 = list.stream().noneMatch(a->a.getAttack()>10);
		System.out.println(b3);
		
		//findFirst-返回第一个元素
		Optional<Card> o1 = list.stream().findFirst();
		System.out.println(o1.orElse(new Card()));
		
		//findAny-返回当前流中的任意元素
		Optional<Card> o2 = list.stream().findFirst();
		System.out.println(o2.get());
		
		//count-返回流中元素的总个数
		long count = list.stream().count();
		System.out.println(count);
		
		//max-返回流中最大值
		Optional o3 = list.stream().max((e1,e2)->{return e1.getAttack()-e2.getAttack();});
		System.out.println(o3.get());
		
		//min-返回流中最小值
		Optional o4 = list.stream().min((e1,e2)->{return e1.getAttack()-e2.getAttack();});
		System.out.println(o4.get());
	}	
}

2. 收集

收集,将流转换为其他形式,接收一个Collertor接口的实现,用于给Stream中元素做汇总的方法

public class Demo10 {
	static List<Card> list = Arrays.asList(
			new Card("了不起的杰弗里斯",3,2),
			new Card("红龙女王阿莱克斯塔萨",8,8),
			new Card("死亡之翼",12,12),
			new Card("小精灵",1,1),
			new Card("转校生",2,2),
			new Card("巫妖王",8,8),
			new Card("魔古山守望者",1,7));
	public static void main(String[] args) {
		//stream流用map映射名字的流,在收集到List容器
		List<String> list1 = list.stream().map(Card::getName).collect(Collectors.toList());
		System.out.println(list1);
		
		//stream流用map映射攻击力的流,在收集到set容器
		Set<Integer> set1 = list.stream().map(Card::getAttack).collect(Collectors.toSet());
		System.out.println(set1);
		
		//Map-把流中所有元素收集到Map中,当出现相同的key时会抛异常
		Map<String, Integer> map = list.stream().collect(Collectors.toMap(Card::getName, Card::getBlood));
		System.out.println(map);
		
		//收集结果为总数
		long count = list.stream().collect(Collectors.counting());
		System.out.println(count);		
	}	
}

collect方法接收一个Collector类型的接口,但由于这个接口内有很多抽象方法,java提供了Collectors工具类,相应的方法直接调用。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java 8中新增的Stream是一种处理集合的优雅姿势。 Stream是对集合(Collection)对象功能的增强,它能以一种声明的方式来处理数据,实现类似于SQL语句的操作。Stream不会改变原有的数据结构,它会生成一个新的Stream,同时支持并行化操作。 Stream的核心思想是将数据看作是,而上可以进行各种操作,比如过滤、排序、映射等。这样可以将数据处理过程变得非常简洁和灵活。 下面是一些Stream的常用操作: 1. filter:过滤符合条件的元素 ``` List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); list.stream().filter(i -> i % 2 == 0).forEach(System.out::println); //输出2, 4 ``` 2. map:将元素转换成另一种类型 ``` List<String> list = Arrays.asList("apple", "banana", "orange"); list.stream().map(s -> s.toUpperCase()).forEach(System.out::println); //输出APPLE, BANANA, ORANGE ``` 3. sorted:对元素进行排序 ``` List<Integer> list = Arrays.asList(5, 2, 1, 4, 3); list.stream().sorted().forEach(System.out::println); //输出1, 2, 3, 4, 5 ``` 4. distinct:去重 ``` List<Integer> list = Arrays.asList(1, 2, 3, 2, 1); list.stream().distinct().forEach(System.out::println); //输出1, 2, 3 ``` 5. limit:限制元素个数 ``` List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); list.stream().limit(3).forEach(System.out::println); //输出1, 2, 3 ``` 6. skip:跳过元素 ``` List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); list.stream().skip(2).forEach(System.out::println); //输出3, 4, 5 ``` 7. reduce:对元素进行聚合操作 ``` List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); int sum = list.stream().reduce(0, (a, b) -> a + b); System.out.println(sum); //输出15 ``` Stream的操作可以组合起来形成一个水线,每个操作都会返回一个新的Stream对象,这样就可以形成一个操作序列。最后调用终止操作(如forEach、findAny等)才会触发所有中间操作的执行。 使用Stream处理集合的代码通常比使用传统的循环更简洁,同时也更易于并行化处理,提高了程序的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值