如何比较两个类的列表,并在两个列表中都出现时返回该类的实例。

huangapple go评论76阅读模式
英文:

how to compare two Lists of a class and return an instance of that class when appearing in both lists

问题

以下是您用Java编写的代码,带有相应的修改和改进,以使其更专业和可读:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

public class Employee {
    
    private String name;
    private int age;
    
    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Employee employee = (Employee) obj;
        return age == employee.age && name.equals(employee.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

public class Main {
    
    public static void main(String[] args) {
        
        List<Employee> list_1 = generateEmployeeList(100);
        List<Employee> list_2 = generateEmployeeList(100);
        
        Set<Employee> commonEmployees = findCommonEmployees(list_1, list_2);
        
        for (Employee employee : commonEmployees) {
            System.out.println("Common employee name: " + employee.getName() +
                               " age: " + employee.getAge());
        }
    }
    
    public static List<Employee> generateEmployeeList(int size) {
        
        List<Employee> employeeList = new ArrayList<>();
        
        Random randomNumberGenerator = new Random();
        
        for (int i = 0; i < size; i++) {
            String name = generateRandomName(randomNumberGenerator);
            int age = randomNumberGenerator.nextInt(20) + 10;
            Employee employee = new Employee(name, age);
            employeeList.add(employee);
        }
        
        return employeeList;
    }
    
    public static String generateRandomName(Random randomNumberGenerator) {
        
        int nameLength = randomNumberGenerator.nextInt(4) + 3;
        StringBuilder nameBuilder = new StringBuilder();
        
        for (int j = 0; j < nameLength; j++) {
            char randomChar = (char) ('a' + randomNumberGenerator.nextInt(26));
            nameBuilder.append(randomChar);
        }
        
        return nameBuilder.toString();
    }
    
    public static Set<Employee> findCommonEmployees(List<Employee> list1, List<Employee> list2) {
        
        Set<Employee> commonEmployees = new HashSet<>();
        
        for (Employee employee : list1) {
            if (list2.contains(employee)) {
                commonEmployees.add(employee);
            }
        }
        
        return commonEmployees;
    }
}

这个修改后的代码做了以下改进:

  1. 重写equals和hashCode方法:在Employee类中重写了equalshashCode方法,这是比较对象相等性的标准做法。这样,您可以使用ListSet来更轻松地比较和存储Employee对象。

  2. 使用Set来寻找相同的员工:使用HashSet来存储共同的员工,因为Set不允许重复元素。这样,您可以轻松找到在两个列表中都存在的员工,而无需显式嵌套循环。

  3. 更清晰的方法和变量命名:改进了方法和变量的命名,使其更加清晰和具有可读性。这有助于代码的理解和维护。

  4. 拆分功能:将生成随机姓名的逻辑拆分为一个独立的方法,使每个方法都专注于单一的任务,提高了代码的可读性和可维护性。

请注意,尽管代码经过了改进,但这只是其中一种可能的优化方式。在编写专业代码时,您还可以考虑使用现有的库函数、设计模式和良好的代码风格来进一步改进代码质量。

英文:

I wrote the below code in Java with the following condition:

  • I created a class for named Employee with two properties Name and Age for employees.
  • An employee’s name and age can be generated randomly (the name doesn’t need to make sense)
  • Employees are equal if their name and age are the same.
  • I created 2 lists made of 100 random instances of the Employee class each.
  • The purpose is to compare both lists and return the instances of Employee that appear in both lists.

I don't know my approach is correct and I don't know how I can improve my code (I mean I wanna make it professional). please help me to correct my approach and make it professional. Thank you in advance.

This is for Employee Class:

public class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}

and the main class is:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Main {
public static Employee employee;
public static void main(String[] args) {
List&lt;Employee&gt; list_1 = nameList(100);
List&lt;Employee&gt; list_2 = nameList(100);
for(int i =0; i&lt;list_1.size(); i++) {
for(int j =0; j&lt;list_1.size(); j++) {
if (list_1.get(i).getName().equals(list_2.get(j).getName()) &amp;&amp;
list_1.get(i).getAge() == list_2.get(j).getAge()) {
System.out.println(&quot;first employee name: &quot; + list_1.get(i).getName() + &quot; first employee age &quot; + list_1.get(i).getAge() + &quot; second employee name: &quot; +
list_2.get(j).getName() + &quot; second employee age: &quot; + list_2.get(j).getAge());
}
}
}
}
public static List&lt;Employee&gt; nameList(int size) {
List&lt;String&gt; nameList  = new ArrayList&lt;&gt;();
List&lt;Integer&gt; ageList = new ArrayList&lt;&gt;();
List&lt;Employee&gt; employeeList = new ArrayList&lt;&gt;();
Random randomNumberGenerator = new Random();
String[] randomName = new String[size];
for(int i = 0; i &lt;randomName.length; i++) {
char[] name = new char[randomNumberGenerator.nextInt(5-2)+3];
for(int j = 0; j &lt; name.length; j++) {
name[j] = (char)(&#39;a&#39; + randomNumberGenerator.nextInt(26));
}
randomName[i] = new String(name);
nameList.add(randomName[i] );
int sss  = randomNumberGenerator.nextInt(20-10) + 12;
ageList.add(sss);
}
for (int i = 0; i &lt; 100; i++) {
employee = new Employee(nameList.get(i),ageList.get(i));
employeeList.add(employee);
}
return employeeList;
}
}

答案1

得分: 2

这里有一个关于如何取两个“列表”交集的示例。你真正想要做的是使用 Set 对象而不是 List 对象。这会使代码更有效率,但使用 Set 而不是 List 还有一个更大的原因。我假设你想要创建两个列表,这两个列表各自都有 100 个独特的项,对吗?如果你使用 List,那么在你的两个包含 100 个员工的列表中不可避免地会出现重复项。而使用 Set,不会出现这种情况,因为 Set 中的项必须是唯一的。如果你生成 100 个随机的员工对象并将它们放入一个 Set 中,最终你会得到少于 100 个员工在这个集合中。但是这个问题是可以解决的。

实际上,得到同时出现在两个列表中的员工列表的魔法是 retainAll 方法。这个方法可以在 Set 和 List 上调用,所以如果你已经有两个已经创建好的列表,你可以在其中一个上调用 retainAll,将另一个列表作为参数传递进去,然后调用该方法的列表将只包含两个列表共有的员工。这就是你直接问题的答案... 使用 retainAll

为了让 Set 的魔法发生,我们需要在 Employee 对象中实现 equalshashCode 方法。对于 List,我们也必须这样做,以使 retainAll 方法正常工作。

为了创建这两个列表/集合,我们不需要迭代 100 次,而是迭代直到我们在每个集合中创建了 100 个唯一的员工为止,通过不断地检查集合的 size()

下面是使用 Set 的完整示例:

package com.inlet.ifserver;

import java.util.*;
import java.util.Random;

public class Test {

    static class Employee {

        private final String name;
        private final int age;

        public Employee(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        public boolean equals(Object obj) {
            if (!(obj instanceof Employee))
                return false;
            return name.equals(((Employee)obj).name) && age == ((Employee)obj).age;
        }

        public int hashCode() {
            return (name + age).hashCode();
        }
    }

    private static final Random random = new Random();
    private static final String[] names = {"Jim", "Jack", "Sam", "Mary", "Kathy", "Sue", "Steve"};

    public static Set<Employee> nameSet(int size) {
        Set<Employee> employeeSet = new HashSet<>();

        while(employeeSet.size() < size) {
            String name = names[random.nextInt(names.length)];
            int age = 12 + random.nextInt(40);
            Employee employee = new Employee(name, age);
            employeeSet.add(employee);
        }
        return employeeSet;
    }

    public static void main(String[] args) {
        Set<Employee> set1 = nameSet(100);
        Set<Employee> set2 = nameSet(100);
        set1.retainAll(set2);
        for (Employee emp: set1)
            System.out.printf("%-6s %2d\n", emp.name, emp.age);
        System.out.printf("Count: %d\n", set1.size());
    }
}

样本结果:

Sue    34
Sue    40
Sam    51
Steve  48
Sue    48
Kathy  22
Steve  16
Jack   28
Mary   44
Jack   26
Sue    15
Kathy  28
Sue    27
Kathy  32
Mary   31
Jack   39
Jack   40
Kathy  42
Jim    31
Mary   22
Jim    34
Sam    16
Kathy  50
Jim    43
Jim    45
Sam    42
Jim    15
Jim    16
Sam    35
Sam    31
Count: 30
英文:

Here's an example of how to intersect two "lists". What you really want to do here is use Set objects instead of List objects. This will make the code more efficient, but there's a bigger reason to use Sets over Lists. I assume that you want to create two lists that truly have 100 unique items in, right? If you use Lists, you will inevitably get duplicates in your two lists of 100 Employees. This can't happen with a Set, as items in a Set must be unique. If you produce 100 random Employee objects and put them in a Set, you'd end up with fewer than 100 Employees in the set. But that can be fixed.

The actual magic of producing the list of Employees that are in both lists is the retainAll method. This can be called on both Sets and Lists, so if you did happen to have two Lists already created, you could call retainAll on one of them, passing the other, and the list you made the call on would then contain just the Employees common to both lists. This is the answer to your direct question...use retainAll!

To allow the Set magic to happen, we had to implement equals and hashCode methods in the Employee object. We would have to do this with Lists too, for the retainAll method to work right.

To create the two lists/Sets, rather than iterating 100 times, we iterate as many times as we have to until we've created 100 unique Employees in each Set, by continually checking the size() of the Set.

Here's a complete example using Sets:

package com.inlet.ifserver;
import java.util.*;
import java.util.Random;
public class Test {
static class Employee {
private final String name;
private final int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean equals(Object obj) {
if (!(obj instanceof Employee))
return false;
return name.equals(((Employee)obj).name) &amp;&amp; age == ((Employee)obj).age;
}
public int hashCode() {
return (name + age).hashCode();
}
}
private static final Random random = new Random();
private static final String[] names = {&quot;Jim&quot;, &quot;Jack&quot;, &quot;Sam&quot;, &quot;Mary&quot;, &quot;Kathy&quot;, &quot;Sue&quot;, &quot;Steve&quot;};
public static Set&lt;Employee&gt; nameSet(int size) {
Set&lt;Employee&gt; employeeSet = new HashSet&lt;&gt;();
while(employeeSet.size() &lt; size) {
String name = names[random.nextInt(names.length)];
int age = 12 + random.nextInt(40);
Employee employee = new Employee(name, age);
employeeSet.add(employee);
}
return employeeSet;
}
public static void main(String[] args) {
Set&lt;Employee&gt; set1 = nameSet(100);
Set&lt;Employee&gt; set2 = nameSet(100);
set1.retainAll(set2);
for (Employee emp: set1)
System.out.printf(&quot;%-6s %2d\n&quot;, emp.name, emp.age);
System.out.printf(&quot;Count: %d\n&quot;, set1.size());
}
}

Sample result:

Sue    34
Sue    40
Sam    51
Steve  48
Sue    48
Kathy  22
Steve  16
Jack   28
Mary   44
Jack   26
Sue    15
Kathy  28
Sue    27
Kathy  32
Mary   31
Jack   39
Jack   40
Kathy  42
Jim    31
Mary   22
Jim    34
Sam    16
Kathy  50
Jim    43
Jim    45
Sam    42
Jim    15
Jim    16
Sam    35
Sam    31
Count: 30

huangapple
  • 本文由 发表于 2020年10月4日 04:18:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/64188608.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定