在ArrayList中搜索对象

时间:2012-02-07 02:10:47

标签: java search object arraylist binary-search

我是Java的新手,我正在为我的编程课程构建一个应用程序,用户可以在其中输入,删除,搜索或编辑学生列表(一个由整数ID号,一个字符串姓氏组成的对象,和双GPA)。到目前为止,我已成功允许用户输入,删除或编辑条目。现在,100多名学生的列表位于ArrayList中(每个都作为具有三个参数的Student对象)。

我的问题是,我不知道允许用户根据ID号,姓氏或GPA(以及将来可能的GPA范围)搜索特定学生的有效方法。我一直在研究Big-O表示法,并希望使用二进制搜索,因为如果学生列表继续增长,这将是一个很好的练习,也是一个更好的选择。到目前为止,对于二进制搜索,我们使用带有while循环的高/低/中间方法(如果这是我当前技能水平的任何指示)。

所以这是我的问题:

根据此标准搜索特定学生的有效方法是什么?我不是在寻找代码或解决我的困境。我真的在寻找Java程序员用来做这些事情的技术或技巧的名称,特别是如果这些技术可以与其他面向对象的编程语言一起使用。

4 个答案:

答案 0 :(得分:4)

我建议查看HashMap数据结构。它允许您将元素存储在映射到某个键的集合中,以便稍后可以通过相同的键检索它们。在您的示例中,您可以使用不同的哈希映射来搜索不同的字段。哈希映射的关键字是字段(即:ID,姓氏或GPA),值将是相应的学生。对于不区分大小写的搜索,请确保在保存对象之前和检索对象之前将密钥(姓氏)转换为小写。

存储ID:

Map<String, Student> idToStudent;

key:&#34; 23213233&#34;,value:&#34; Some Student&#34;;

考虑重复的名称或gpa,然后使用类型的地图:

Map<String, List<Student>> lastNameToStudents;

key:&#34; smith&#34;,value:[&#34; John Smith&#34;,&#34; Bob Smith&#34;等]

Map<Double, List<Student>> gpaToStudents:

键:&#34; 2.4&#34;,价值:[&#34;学生1&#34;,&#34;学生2&#34;等];

请注意,为了简洁起见,我使用了学生姓名的字符串表示,但实际上这些代表了Student个实例。

答案 1 :(得分:2)

对于二进制搜索,您需要按照您要搜索的条件对列表进行排序。

您可以维护三个不同的列表,按您需要的三个不同标准排序:

ArrayList<Student> sortedByName;
ArrayList<Student> sortedByGpa;
ArrayList<Student> sortedById;

public List<Student> getStudentByName(String name){
    return binarySearchOnName(sortedByName, name);
}
public List<Student> getStudentByGpa(double gpa){
    return binarySearchOnGpa(sortedByGpa, gpa);
}
...

请注意,当您将新的Student插入ArrayList时,您还应该将该Student插入到其他已排序的ArrayLists中的正确位置。 (当然,您可以使用二进制搜索来完成此操作。)

答案 2 :(得分:1)

您需要重复或任意排序吗?如果没有,请考虑使用TreeSet或HashSet。 TreeSet提供O(log(n))访问/插入/删除并自动对其元素进行排序(因此迭代它会按排序顺序获取元素.HashSet提供分摊的O(1)访问/插入/删除,但迭代发生在一些随机顺序(你无法控制)。其中一个听起来像是实现目标的最简单方法。

如果你需要按成员搜索,你可能想要一个HashMap / TreeMap,只要你不介意只获得完全匹配。如果您需要按成员搜索多个成员,您可能需要多个地图,每个要搜索的地图都有一个地图。如果您要使用ArrayLists并且想要比O(n)查找更好,那么无论如何都需要多个列表(每个查找参数列出1个列表)。

最后,O(n)查找将是最简单的。只要列表不会太大(想想10000个元素而不是100个),性能就会很好,这种方法可以最大限度地减少存储开销。您不希望过早优化 - 在性能出现问题之前,最好的方法就是遍历列表。

答案 3 :(得分:1)

所以我看到一个普遍问题的三个问题。一般问题是您希望能够搜索某些标准,其中三个问题是每个标准的具体情况。因此唯一保证唯一的字段是学生ID字段。这允许我们覆盖equals + hashcode方法。我们希望这是我们用来确定相等性的值(至少在这个非常简单的例子中)。通过执行此操作,您将通过以下调用公开一种机制,以便在列表中进行搜索而不进行排序:

list.contains(Student);

现在就名称而言,由于这个值不能保证是唯一的,我们希望做类似的事情:

 matchedStudents = new ArrayList<Student>();
    for(Student currentStudent : studentList)  
    {  
        if(currentStudent.getName().equalsIgnoreCase(searchString)  
        {
              matchedStudents.add(currentStudent);  
        }
    }  
      return matchedStudents;

就GPA而言,我们基本上会重复上面的循环,只使用GPA == searchCriteria。

据说应该可以写出这样的函数:

function searchStudent(String searchString, String type)  
{    
    //type is one of: GPA, name, ID  
    switch(type)  
    {  
       case gpa:  
       case id:  
       case name:
    }  
}  

应该让你开始。