java8新特性Stream流操作详解及实战3

Posted 孔子-说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java8新特性Stream流操作详解及实战3相关的知识,希望对你有一定的参考价值。

原文地址:java8新特性Stream流操作详解及实战3

java8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda,给我们操作集合(Collection)提供了极大的便利。本文主要介绍Stream的排序、去重、合并操作,以及常用方法简单汇总。

5、Stream常用操作示例实战

Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Stream中的元素是以Optional类型存在的。

创建一个案例使用的员工类Person:

class Person 
	private String name;  // 姓名
	private int salary; // 薪资
	private int age; // 年龄
	private String sex; //性别
	private String area;  // 地区

	// 构造方法
	public Person(String name, int salary, int age,String sex,String area) 
		this.name = name;
		this.salary = salary;
		this.age = age;
		this.sex = sex;
		this.area = area;
	
	// 省略了get和set,请自行添加


5.7 排序(sorted)

sorted,中间操作。有两种排序:

  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):Comparator排序器自定义排序

sorted源码

   Stream<T> sorted();

   @Override
   public final Stream<P_OUT> sorted() 
       return SortedOps.makeRef(this);
   

sorted(Comparator com)源码

  	Stream<T> sorted(Comparator<? super T> comparator);

	@Override
   public final Stream<P_OUT> sorted(Comparator<? super P_OUT> comparator) 
       return SortedOps.makeRef(this, comparator);
   

示例:

将员工按工资由高到低(工资一样则按年龄由大到小)排序

public class StreamTest 
	public static void main(String[] args) 
		List<Person> personList = new ArrayList<Person>();

		personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
		personList.add(new Person("Tom", 8900, 22, "male", "Washington"));
		personList.add(new Person("Jack", 9000, 25, "male", "Washington"));
		personList.add(new Person("Lily", 8800, 26, "male", "New York"));
		personList.add(new Person("Alisa", 9000, 26, "female", "New York"));

		// 按工资升序排序(自然排序)
		List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
				.collect(Collectors.toList());
		// 按工资倒序排序
		List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
				.map(Person::getName).collect(Collectors.toList());
		// 先按工资再按年龄升序排序
		List<String> newList3 = personList.stream()
				.sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
				.collect(Collectors.toList());
		// 先按工资再按年龄自定义排序(降序)
		List<String> newList4 = personList.stream().sorted((p1, p2) -> 
			if (p1.getSalary() == p2.getSalary()) 
				return p2.getAge() - p1.getAge();
			 else 
				return p2.getSalary() - p1.getSalary();
			
		).map(Person::getName).collect(Collectors.toList());

		System.out.println("按工资升序排序:" + newList);
		System.out.println("按工资降序排序:" + newList2);
		System.out.println("先按工资再按年龄升序排序:" + newList3);
		System.out.println("先按工资再按年龄自定义降序排序:" + newList4);
	

5.8 去重、合并(distinct、skip、limit)

流也可以进行合并、去重、限制、跳过等切片操作。

  • limit(n):获取n个元素,限制获取元素的个数
  • skip(n):跳过n元素,配合limit(n)可实现分页
  • distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

distinct(去重)源码

Stream<T> distinct();

@Override
   public final Stream<P_OUT> distinct() 
       return DistinctOps.makeRef(this);
   

skip(跳过)源码

Stream<T> skip(long n);

@Override
   public final Stream<P_OUT> skip(long n) 
       if (n < 0)
           throw new IllegalArgumentException(Long.toString(n));
       if (n == 0)
           return this;
       else
           return SliceOps.makeRef(this, n, -1);
   

limit源码

Stream<T> limit(long maxSize);

 @Override
   public final Stream<P_OUT> limit(long maxSize) 
       if (maxSize < 0)
           throw new IllegalArgumentException(Long.toString(maxSize));
       return SliceOps.makeRef(this, 0, maxSize);
   

示例:

public class StreamTest 
	public static void main(String[] args) 
		String[] arr1 =  "a", "b", "c", "d" ;
		String[] arr2 =  "d", "e", "f", "g" ;

		Stream<String> stream1 = Stream.of(arr1);
		Stream<String> stream2 = Stream.of(arr2);
		// concat:合并两个流 distinct:去重
		List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
		// limit:限制从流中获得前n个数据
		List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
		// skip:跳过前n个数据  这里的1代表把1代入后边的计算表达式
		List<Integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());

		System.out.println("流合并:" + newList);
		System.out.println("limit:" + collect);
		System.out.println("skip:" + collect2);
	

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wa9Y4zRn-1667957752122)(/upload/2022/07/image-1657590174931.png)]

6、常用方法简单汇总

6.1 计算两个list中的差集

//计算两个list中的差集
List<String> reduce1 = allList.stream().filter(item -> !wList.contains(item)).collect(Collectors.toList());

6.2 stream() 和 parallelStream()

使用Collection下的 stream() 和 parallelStream() 方法(最为常用)

List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();  //顺序流
Stream<String> stringStream = list.parallelStream(); //并行流

6.3 将数组转成流

使用Arrays 中的 stream() 方法,将数组转成流

Integer[] nums = new Integer[]10,2,3,5;
Stream<Integer> Integerstream = Arrays.stream(nums);

6.4 静态方法of()、iterate()、generate()

使用Stream中的静态方法:of()、iterate()、generate()

Stream<Integer> TestStream = Stream.of(1,2,3,4);
//iterate()、generate()方法可以创建无限流,可以通过limit()方法来限制数量。
Stream<Integer> TestStream2 = Stream.iterate(0,x->x+2);
Stream<Integer> TestStream3 = Stream.generate(()-> new Random().nextInt(10));
Stream<Integer> TestStream4 = Stream.iterate(0,x->x+2).limit(10);

6.5 文件内容转为流

使用 BufferedReader.lines() 方法,将每行内容转成流

BufferedReader reader = new BufferedReader(new FileReader("F:\\\\test_stream.txt"));
Stream<String> lineStream = reader.lines();
//上面可以写成一行
Stream<String> lineStream2 = new BufferedReader(new FileReader("F:\\\\test_stream.txt")).lines();

6.6 字符串分隔成流

使用 Pattern.splitAsStream() 方法,将字符串分隔成流

Pattern pattern = Pattern.compile(",");
Stream<String> stringStream2 = pattern.splitAsStream("a,b,c,d");

6.7 筛选与切片

  • filter:过滤流中的某些元素
  • limit(n):获取n个元素,限制获取元素的个数
  • skip(n):跳过n元素,配合limit(n)可实现分页
  • distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
Stream<Integer> stream = Stream.of(6,6,6,12,22,12,213,111,7,9,10);
Stream<Integer> streamFilter = stream.filter(item -> item > 10) // 12 22 12 213 111
        .distinct() //12 22 213 111
        .skip(2) //213 111
        .limit(1);//213
streamFilter.forEach(System.out::println);

6.8 匹配、聚合操作

  • allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
  • noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
  • anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
  • findFirst:返回流中第一个元素
  • findAny:返回流中的任意元素
  • count:返回流中元素的总个数
  • max:返回流中元素最大值
  • min:返回流中元素最小值
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);  

boolean allMatch = list.stream().allMatch(e -> e > 10); //false
boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true
boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true 

Integer findFirst = list.stream().findFirst().get(); //1
Integer findAny = list.stream().findAny().get(); //1 

long count = list.stream().count(); //5
Integer max = list.stream().max(Integer::compareTo).get(); //5
Integer min = list.stream().min(Integer::compareTo).get(); //1 

以上是关于java8新特性Stream流操作详解及实战3的主要内容,如果未能解决你的问题,请参考以下文章

java8新特性Stream流操作详解及实战3

Java8新特性及实战视频教程完整版

Java8新特性:StreamAPI(超详解)

Java8新特性--Stream流操作

JAVA8新特性--集合流操作Stream

乐字节-Java8新特性-接口默认方法之Stream流(下)