【问题标题】:How can i ensure that only unique objects are created in java我如何确保在 java 中只创建唯一的对象
【发布时间】:2016-10-21 17:21:24
【问题描述】:

这是一个面试问题,我一无所有,没有任何想法。 假设我有一个 Employee 类,它包含三个字段 EmpIdEmpNameEmpAddress

现在我的工作是确保我创建的所有对象在EmpId 的基础上都是唯一的,这样当我尝试创建两个具有相同EmpId 的对象时,必须有一种机制来停止/警告关于它,也许编译器警报或任何逻辑都可以。

我在采访中唯一能想到的就是使用Map(即HashMap),其键为EmpId,以确保唯一性。 我知道 DB 中的主键可以确保这一点,但我如何在 Java 本身中处理它。

对此类行的任何建议/想法将不胜感激。

【问题讨论】:

  • “编译器不允许我这样做”你确定这部分作业吗?
  • 听起来您需要以确保唯一性的方式生成EmpId,而不是让用户创建任意值。同步的静态工厂方法可以为此工作。同步工厂方法也适用于您的地图创意。
  • 您的解决方案看起来不错。具有同步访问的static long 计数器将是一个更简单的解决方案。
  • 好吧,如果允许框架,这可以很容易地在 java 中使用带有主键注释的 Hibernate 来完成。
  • EmpId 必须作为构造函数参数传递吗?如果没有,您可以参考@MadPhysicist 的建议。

标签: java sorting collections unique


【解决方案1】:

我可以想很多办法。例如1

  1. 使用将 EmpId 映射到 Employee 的常规 Map。
  2. 使用一组 EmpId。
  3. 使用数据库表,其中每一行代表一个员工,EmpId 是主键。
  4. 使用序列生成器2 生成唯一的 EmpId 值序列,并且不允许 Employee 对象构造函数的调用者提供 EmpId。
  5. 如果 EmpId 是整数且空间密集,请使用位图或 BitSet 而不是一组 EmpId。
  6. 如果 EmpId 是整数并且空间非常密集,您可以使用 TreeMap 来表示 EmpId 的范围。 (逻辑有点复杂。)

1 - 还有其他各种“糟糕”的解决方案,我不会一一列举。

2 - 这并没有真正解决问题如上所述。但是,这可能是您在实践中实施的方式;例如使用 SQL SEQUENCE。

【讨论】:

    【解决方案2】:

    正如其他人所说,您可以使用MapSet 来保存您的集合,并覆盖equalshashCode 方法以确保在集合中正确使用。

    如果你想检查对象的创建,你可以例如使用Map 并抛出异常:

    import java.util.Set;
    import java.util.HashSet;    
    
    public class Employee {
    
        private static Map<EmpID, Employee> employees = new HashMap<EmpID, Employee>();
    
        private EmpId empID;
        private EmpName empName;
        private EmpAddress address;
    
        public Employee(EmpID empID, EmpName empName, EmpAddress empAddress) throws NotUniqueIDException {            
            if(!employees.keySet().contains(empID) {
                this.empID = empID;
                this.empName = empName;
                this.empAddress = empAddress;
                employees.put(empID, this);
            } else {
                // Error
                throw NotUniqueIDException();
            }
        }
    

    然后,使用时:

    try {
        Employee employee = new Employee(empID, empName, empAddress);
    } catch(NotUniqueIDException exception) {
        // Do something here
    }
    

    至于如果您需要生成唯一 ID,UUID.randomUUID() 可能值得一看

    【讨论】:

      【解决方案3】:

      我认为您可以使用 HashSet 或类 Set 的其他实现并覆盖方法 equals 避免类的重复条目。

      来自类 Set 的 Java documentation

      Collections Framework 接口中的许多方法都是用术语定义的 的equals方法。

      注意 HashSet 和 Set 实现接口 Collection

      我将向您展示一个使用 contains

      方法避免重复的示例

      来自 Java documentation 的方法包含的类 Set

      布尔包含(对象o)

      如果此集合包含,则返回 true 指定的元素。更正式地说,当且仅当 集合至少包含一个元素 e 使得 (o==null ? e==null : o.equals(e))。

      在这段代码中,我使用了一个静态 HashSet 来获得一个唯一的 Employee 列表。只有在成功将元素插入 HashSet 时,才能使用返回 true 的方法 addToSet 在集合中插入元素。

      import java.util.HashSet; 
      
      public class Employee {
          private static HashSet<Employee> EmpSet= new HashSet<>();
          private String EmpId, EmpName, EmpAddress;
          
          public Employee(String id, String name, String addr){
              EmpId = id;
              EmpName = name;
              EmpAddress = addr;
          }
          
          public static boolean addToSet(Employee employee){  //this can be synchronized if you need
              if(EmpSet.contains(employee))
                  return false;
              else
                  EmpSet.add(employee);
              return true;
          }
          
          @Override
          public boolean equals(Object to_compare){
              if( !(to_compare instanceof Employee))
                  return false;
              Employee other = (Employee) to_compare;
              return this.EmpId.equals(other.EmpId);
          }
      }
      

      如果 EmpId 为 Integer 或 Long,则显示的代码也有效。 如果您在多个线程中使用此类,则可以按照 cmets 中的建议使方法 addToSet 同步。

      如果您使用的是数据库,此代码无效,您可以找到针对该特定情况的特定方法。

      编辑 对不起,其实你不需要addToSet方法,因为HashMap类的方法add做的完全一样,所以你可以使用它的方法或者干脆:

      public static boolean addToSet(Employee employee){  //this can be synchronized if you need
                      EmpSet.add(employee);
              }
      

      【讨论】:

        【解决方案4】:

        很简单,我们需要重写 equals() 方法,黄金法则说,当你重写 equals() 时,我们必须重写 hascode()。
        这是这个的工作代码

            class Employee
            {
                private Integer id;
                private String firstname;
                private String lastName;
                private String department;
            
                Employee(Integer id, String firstname, String lastName, String department) {
                    this.id = id;
                    this.firstname = firstname;
                    this.lastName = lastName;
                    this.department = department;
                }
            
                public Integer getId() {
                    return id;
                }
                
                public String getFirstname() {
                    return firstname;
                }
                
                public String getLastName() {
                    return lastName;
                }
                
                public String getDepartment() {
                    return department;
                }
                
                public boolean equals(Object o) {
                    if(o == null)
                    {
                        return false;
                    }
                    if (o == this)
                    {
                        return true;
                    }
                    if (getClass() != o.getClass())
                    {
                        return false;
                    }
            
                    Employee e = (Employee) o;
                    return (this.getId() == e.getId());
                }
                
            
                public int hashCode()
                {
                    final int PRIME = 31;
                    int result = 1;
                    result = PRIME * result + getId();
                    return result;
                }
            }
        

        驱动类

        public class Test {
        
            public static void main(String[] args) {
                Employee e1 = new Employee(100,"Arpit","Agarwal","SDET");
                Employee e2 = new Employee(101,"Neha","Agrawal","Web Developer");
                Employee e3 = new Employee(103,"Priya","Gupta","Data Science");
                Employee e4 = new Employee(100,"Mohit","Verma","Dev ops");
                Set<Employee> mySet = new LinkedHashSet<>();
                mySet.add(e1);
                mySet.add(e2);
                mySet.add(e3);
                mySet.add(e4);
                for(Employee obj : mySet)   {
                    System.out.println(obj.getId() + ", " + obj.getFirstname() + ", " + obj.getLastName() + ", " + obj.getDepartment());
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-23
          • 2021-12-04
          • 2020-12-04
          • 1970-01-01
          • 2013-12-06
          • 2023-02-04
          • 1970-01-01
          相关资源
          最近更新 更多