比较对象

时间:2009-11-07 10:47:47

标签: java algorithm

我有两个学生对象。

class Student{
int physics;
int english;
int chemistry;
}

我需要将每个科目的学生A分数与所有科目的学生B分数进行比较。

物理学中的标记需要与物理,英语,化学中的B标记进行比较。 同样A的英语与B的所有三个。

如果至少有一个比赛说A的化学标记等于B的英文标记, 然后停止执行并返回false。

我的逻辑是

if(a.getPhysics==b.getPhysics || a.getPhysics==b.getEnglish || a.phy==b.chem ||  ...){
   return false;
 }

这是更好还是其他任何好的逻辑??????

6 个答案:

答案 0 :(得分:1)

稍微改进就是在Student类中创建一个方法来实现它。

答案 1 :(得分:1)

嗯,在任何情况下你都必须进行O(n^2)比较,问题是代码的清洁程度。

你现在建议的6个布尔比较是好的,如果你有30个科目怎么办?你会保持你需要进行的数百次比较吗?

保持简单,我希望将成绩保持在ListMap,然后进行嵌套迭代:

for (int gradeA : thisStudent.getGrades()) {
    for (int gradeB : otherStudent.getGrades()) {
        if (gradeA == gradeB) return false;
    }
}
return true;

当然这个代码需要适应你的场景(List vs. Map上的不同迭代,每次不检查每个等级的优化,从中提取方法等等)

答案 2 :(得分:1)

这些属性(课程物理,英语,......)不应该在Student课程中。一个更好的选择是创建一个CourseModel,您可以在其中存储所有课程,并跟踪所有注册课程的Student。从您的CourseModel,您可以查询特定的Student并获取所有课程(作为数组/集合)。当你有两个集合/数组时,只需创建一个嵌套的for语句来比较所有这些。

答案 3 :(得分:1)

使用HashSet:

Set<Integer> aMarks = new HashSet<Integer>();
Set<Integer> bMarks = new HashSet<Integer>();

Collections.addAll(aMarks, 2, 3, 9);
Collections.addAll(bMarks, 4, 2, 2);

boolean check = Collections.disjoint(aMarks, bMarks);
return check;

这些值仅供测试。您可以使用新方法Student.getMarksAsSet()

更改Collections.addAll(...)

答案 4 :(得分:1)

您可以为Student添加将其标记作为集合返回的功能:

public class Student {
   private int physics;
   private int english;
   private int chemistry;

   public Student(int physics, int english, int chemistry) {
      this.physics = physics;
      this.english = english;
      this.chemistry = chemistry;
   }

   public Set<Integer> marks() {
      return new HashSet<Integer>(Arrays.asList(physics, english, chemistry));
   }
}

然后,当试图确定两个学生是否匹配时,你需要看到的是他们的两组标记是否是不相交的,如StudentMatcher所做的那样:

public class StudentMatcher {
   public boolean matches(Student student1, Student student2) {
      Set<Integer> studentMarks1 = student1.marks();
      Set<Integer> studentMarks2 = student2.marks();
      return haveIntersection(studentMarks1, studentMarks2);
   }

   private boolean haveIntersection(Set<Integer> studentMarks1, Set<Integer> studentMarks2) {
      return studentMarks1.removeAll(studentMarks2);
   }
}

以下是验证其有效的单元测试:

public class StudentMatcherTest {
   @Test
   public void matches() {
      StudentMatcher matcher = new StudentMatcher();
      Student student1 = new Student(34, 45, 66);
      Student student2 = new Student(99, 55, 34);
      Student student3 = new Student(11, 22, 33);

      assertTrue("Should match", matcher.matches(student1, student2));
      assertFalse("Should not match", matcher.matches(student1, student3));
   }
}

可以做的更多,以使这更好,但我认为你的代码比你发布的更复杂,所以希望这足以让你走上更好的道路。

答案 5 :(得分:0)

如果标记在一个小范围内(AF而不是百分比),并且您需要比较许多主题中的标记而不是您给出的三个标记,请填充一组布尔值以保存第一个学生是否具有给定标记,然后第二次检查数组是否有值集。那将是O(N + M),其中N是受试者的数量,M是可能等级的数量。

如果你只有三个科目,那么硬编码的测试并不是那么糟糕 - 你需要六行才能从中获得标记。