Java 8 Stream 中的属性不同
本文通过属性演示了在 Java 中使用流的独特功能。
Java 8 Stream 中的属性不同
Java 8 Stream 有一个 distinct()
方法,可以过滤列表中的重复项。 此方法使用实例中的 equal 方法来检查唯一元素,如果发现重复项,则将其删除。
如果需要将 distinct()
方法应用于某个属性或字段,我们就不能使用它。 但是我们可以使用特定的方式按属性应用 distinct()
方法。
让我们尝试一个例子,我们创建一个 Employee 类,其中包含员工的姓名和 id,然后尝试在 Employee 类列表的流中使用 unique()
方法:
package jiyik;
import java.util.List;
import java.util.Objects;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
public static void main(String[] args){
List<Employee> Employee_List = List.of(
new Employee("Sheeraz", 10),
new Employee("John", 20),
new Employee("Sheeraz", 30),
new Employee("Robert", 40),
new Employee("Jake", 50),
new Employee("Logan", 60)
);
//the distinct() will remove the duplicates by equals
Employee_List.stream()
.distinct()
.forEach(System.out::println);
}
}
上面的代码将在使用流的 Employee 类列表上使用 unique()
方法,并删除具有相同值的条目。 代码展示了 distinct()
方法的简单使用。
现在,让我们看看如何在 Java 中按属性应用不同的逻辑。
使用Collectors.toMap在Java中应用Distinct by Property
我们可以使用 Collectors.toMap 将流的元素收集到映射中,以由属性或字段作为键控。 该映射对于一个键只能有一个值,因此我们需要为每个键选择第一个流对象。
我们可以从结果映射中调用 values()
,它应用不同的逻辑并通过我们分组的自定义属性为我们提供唯一的值。 让我们看一个例子:
package jiyik;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
public static void main(String[] args){
List<Employee> Employee_List = List.of(
new Employee("Sheeraz", 10),
new Employee("John", 20),
new Employee("Sheeraz", 30),
new Employee("Robert", 40),
new Employee("Jake", 50),
new Employee("Logan", 60)
);
Collection<Employee> Unique_EmployeeList = Employee_List.stream()
.collect(Collectors.toMap(Employee::getName, Function.identity(),
(Employee1, Employee2) -> Employee1))
.values();
System.out.println(Unique_EmployeeList);
}
}
上面的代码将使用基于 Employee_Name 属性的 Collection.toMap 方法在流上应用不同的逻辑,这意味着代码将返回具有唯一员工姓名的列表。 查看输出:
[Jake 50, Logan 60, Robert 40, John 20, Sheeraz 10]
我们可以看到,Employee 列表中有两个名为 Sheeraz 的条目,其中一个被删除,因为我们根据 name 属性应用了不同的值。
使用包装类在 Java 中应用“按属性区分”
我们还可以创建一个包装类,将属性分配给 Employee 类,然后按包装类中的属性应用distinct() 方法。 包装类将是私有静态的并在驱动程序类中声明。
参见示例:
package jiyik;
import java.util.List;
import java.util.Objects;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
private static class EmployeeWrapper {
private Employee Employee;
private EmployeeWrapper(Employee Employee) {
this.Employee = Employee;
}
public Employee getEmployee() {
return Employee;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
EmployeeWrapper other = (EmployeeWrapper) Demo_Object;
return Objects.equals(Employee.getName(), other.Employee.getName());
}
@Override
public int hashCode() {
return Objects.hash(Employee.getName());
}
}
public static void main(String[] args){
List<Employee> Employee_List = List.of(
new Employee("Sheeraz", 10),
new Employee("John", 20),
new Employee("Sheeraz", 30),
new Employee("Robert", 40),
new Employee("Jake", 50),
new Employee("Logan", 60)
);
Employee_List.stream()
.map(EmployeeWrapper::new)
.distinct()
.map(EmployeeWrapper::getEmployee)
.forEach(System.out::println);
}
}
上面的代码使用包装类 EmployeeWrapper 和流中的 unique()
方法来获取具有唯一名称的员工列表。 我们可以看到,在包装类中,我们在 equals()
方法中分配了属性名称,然后我们在驱动类中使用它。
查看输出:
Sheeraz 10
John 20
Robert 40
Jake 50
Logan 60
使用distinctByKey方法在Java中应用Distinct by Property
在这种方法中,我们必须使用并发哈希映射来查找是否存在具有相同值的现有键。 该方法将在驱动程序类中声明,然后通过 filter()
方法在流中使用。
参见示例:
package jiyik;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class Employee {
private String Employee_Name;
private int Employee_ID;
public Employee(String Employee_Name, int Employee_ID) {
this.Employee_Name = Employee_Name;
this.Employee_ID = Employee_ID;
}
public String getName() {
return Employee_Name;
}
public int getID() {
return Employee_ID;
}
@Override
public boolean equals(Object Demo_Object) {
if (this == Demo_Object) {
return true;
}
if (Demo_Object == null) {
return false;
}
if (getClass() != Demo_Object.getClass()) {
return false;
}
Employee other = (Employee) Demo_Object;
return Objects.equals(Employee_Name, other.Employee_Name);
}
@Override
public int hashCode() {
return Objects.hash(Employee_Name);
}
@Override
public String toString() {
return Employee_Name + " " + Employee_ID;
}
}
public class Example {
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> Key_Extractor)
{
Map<Object, Boolean> Employee_Map = new ConcurrentHashMap<>();
return t -> Employee_Map.putIfAbsent(Key_Extractor.apply(t), Boolean.TRUE) == null;
}
public static void main(String[] args){
List<Employee> Employee_List = List.of(
new Employee("Sheeraz", 10),
new Employee("John", 20),
new Employee("Sheeraz", 30),
new Employee("Robert", 40),
new Employee("Jake", 50),
new Employee("Logan", 60)
);
// Get distinct objects by one key
List<Employee> Distinct_Employees1 = Employee_List.stream()
.filter( distinctByKey(p -> p.getName() ) )
.collect( Collectors.toList() );
System.out.println( Distinct_Employees1 );
// Get distinct objects by one key
List<Employee> Distinct_Employees2 = Employee_List.stream()
.filter( distinctByKey(p -> p.getName() + " "+ p.getID() ) )
.collect( Collectors.toList() );
System.out.println( Distinct_Employees2 );
}
}
上面的代码尝试根据名称以及名称和 ID 获取不同的元素。 查看输出:
[Sheeraz 10, John 20, Robert 40, Jake 50, Logan 60]
[Sheeraz 10, John 20, Sheeraz 30, Robert 40, Jake 50, Logan 60]
正如我们所看到的,第一个列表仅通过 name 属性来区分,第二个列表通过 name 和 ID 属性来区分。
相关文章
Java迭代器remove()方法
发布时间:2023/07/17 浏览次数:117 分类:Java
-
Java 开发人员经常需要在迭代时从 ArrayList 中删除元素或对象。在本文中,我们将了解迭代器的remove()方法和集合的remove()方法的工作原理有何不同。
查找 Java 中的内存泄漏
发布时间:2023/07/17 浏览次数:96 分类:Java
-
本文将教我们如何查找Java内存泄漏。未使用的项目占用额外的内存空间称为内存泄漏。 内存泄漏是有问题的,因为它们会堵塞内存资源并随着时间的推移降低系统性能。
在 Java 中对一个 Switch Case 语句使用多个值
发布时间:2023/07/16 浏览次数:174 分类:Java
-
在本文中,我们将学习如何在一个 switch-case 语句中使用多个值。使用 switch-case 语句 Java 允许程序员通过使用 switch case 语句来像其他编程语言一样克服太多的 if-else 条件语句。
Java 中的线程安全延迟初始化
发布时间:2023/07/16 浏览次数:59 分类:Java
-
本文将讨论在 Java 中实现线程安全的延迟初始化。Java 中的对象初始化 延迟初始化是延迟对象创建的行为。 它还可能导致某些计算任务或首次昂贵流程的延迟。
在 Java 中显示动画 GIF
发布时间:2023/07/16 浏览次数:112 分类:Java
-
我们可以使用javax包的Swing库方法来在Java中显示动画GIF。 本文介绍用户如何在 Java 应用程序或单独的窗口中显示动画 GIF。使用 Javax.swing 库在 Java 中显示动画 GIF
在 Java 中用 %20 替换空格
发布时间:2023/07/16 浏览次数:96 分类:Java
-
在本文中,我们将学习两种用 %20 替换给定字符串的所有空格的方法。Java中使用replaceAll()方法将空格替换为%20 在这里,我们使用Java内置方法 replaceAll() 将所有空格替换为%20字符串。
Java 中的矩阵乘法
发布时间:2023/07/16 浏览次数:99 分类:Java
-
在本文中,我们将学习在 Java 中将两个矩阵相乘。Java 中两个矩阵相乘 我们使用乘法和加法运算符来乘两个矩阵。
Java Synchronised变量
发布时间:2023/07/16 浏览次数:131 分类:Java
-
本文将讨论如何在Java中同步或锁定变量。同步或锁定是避免此类错误情况的解决方案。 synchronized 关键字