Java 8引入的stream()是一个强大的工具,它让集合操作变得更加简单和优雅。stream()中的filter()方法是stream()的一个重要部分,它可以对数据进行筛选和过滤,让我们只留下需要的数据。因此,本文将介绍如何使用Java中的stream().filter方法。
一、filter()方法的定义和用途
filter()方法是一个中间操作,它接受一个lambda表达式作为参数,该表达式返回一个boolean类型的值。它的作用是过滤掉不需要的元素,只保留需要的元素。
在 stream().filter() 方法中,我们需要传入一个谓词(Predicate)参数,这个谓词接受一个类型为T的对象作为输入,返回一个布尔值:
public interface Predicate<T> {
boolean test(T t);
}
下列代码可以对一个list列表进行过滤,让最终的结果只保留age属性大于等于18的元素:
List<Person> people = getPeople();
List<Person> adultPeople = people.stream()
.filter(person -> person.getAge() >= 18)
.collect(Collectors.toList());
其中getPeople()方法返回了一个Person类型的List,Person对象有一个age属性。
二、filter()方法和其他Stream API的联合使用
1. 将过滤后的结果转换为一个数组
在上述示例中,使用collect(Collectors.toList())方法将过滤后的结果转换为一个List,但是我们也可以将它转换为一个数组:
List<Person> people = getPeople();
Person[] adultPeople = people.stream()
.filter(person -> person.getAge() >= 18)
.toArray(Person[]::new);
其中toArray()方法的参数类型是一个 IntFunction<T[]>泛型接口,它的声明如下:
@FunctionalInterface
public interface IntFunction<R> {
R apply(int value);
}
该接口接受一个 int 值,返回一个指定类型的结果。 在本例中,我们将 toArray() 的参数设置为构造器引用Person[]::new,创建一个 Person 类型的数组作为结果。
2. 过滤流中的某个特定值
我们可以使用 filter() 方法轻松地过滤掉某个特定的值。在下面的例子中,我们将过滤掉字符串列表中的"Sam"。
List<String> names = Arrays.asList("John", "Sam", "Alex");
List<String> updatedNames = names.stream()
.filter(name -> !"Sam".equals(name))
.collect(Collectors.toList());
在这个例子中,我们使用 "!" 作为逻辑非运算符。 因此,当 name 的值与 "Sam" 相等时,谓词将返回 false。如此一来,Sam 就被过滤掉了。
3. 过滤集合中的重复元素
我们可以使用 Stream 类中的 distinct() 方法来过滤集合中的重复元素。在下列示例中,展示了如何使用 distinct() 方法来筛选出一个列表的唯一元素:
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 5, 5, 5);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
在这个例子中,我们将 numbers 列表中的重复元素过滤掉,并使用 collect(Collectors.toList()) 方法将结果转换为一个List对象.
三、常见错误以及如何避免它们
1. NullPointerException
如果在filter()方法中传入了一个null值,就会抛出NullPointerException异常。为了避免这种错误,我们应该检查集合中是否包含空值,或者使用Optional类:
List<Person> people = getPeople();
List<Person> nonNullPeople = people.stream()
.filter(Objects::nonNull)
.filter(person -> person.getAge() >= 18)
.collect(Collectors.toList());
在上述示例中,我们使用了一个名为 Objects.nonNull() 的静态方法,它可以检查一个对象是否为 null,如果不是就返回 true。
2. 类型转换问题
在进行类型转换时,经常会出现 ClassCastException。为了避免这种情况,我们可以使用instanceof运算符来检查类型是否一致:
Object[] values = {1, "Sam", 2.0f, };
List<String> stringValues = Arrays.stream(values)
.filter(String.class::isInstance)
.map(String.class::cast)
.collect(Collectors.toList());
在上述示例中,我们使用isInstance()方法检查元素是否为String,如果是String,map()方法就会将其强制转换为String类型。
3. 并行处理效率问题
在使用stream()方法进行并行处理时,我们也需要注意效率问题。并行处理需要在内存中创建多个线程来处理不同的数据块,这可能会导致操作效率变慢。 因此,在进行并行处理时,我们需要仔细考虑输入数据的大小、内存使用情况和硬件设备。
在下列示例中,我们展现了如何使用parallel()方法进行并行处理:
List<Person> people = getPeople();
List<Person> adultPeople = people.parallelStream()
.filter(person -> person.getAge() >= 18)
.collect(Collectors.toList());
四、总结
Java中的filter()方法提供了一个简单而优雅的方式来处理集合中的元素,让我们只留下我们需要的数据。在介绍了Java中的stream().filter方法及其常见用法后,我们应该注意一些常见的错误,如空类型和类型转换。
作为Java开发者,熟练掌握stream().filter方法可以使我们更加有效地编写高质量的代码。