如何按字母顺序将值输入ArrayList

时间:2019-03-24 00:01:15

标签: java arraylist

我被赋予了按字母顺序将值添加到ArrayList中的任务(按姓氏,如果姓氏相同,则按名字),一旦给出所有输入,就不允许对ArrayList进行排序。我想做的是确定每次给出输入时值应位于的位置并将其放置在该位置。值示例:输入为{John Doe,Bryan Sully,Harry Ache,Ali Doe,Bry Dyre},输出应为{Harry Ache,Ali Doe,John Doe,Bry Dyre,Bryan Sully}。但是,在姓氏相同的情况下,{Harry Ache,Ali Doe,Bry Dyre,John Doe和Bryan Sully}会出现什么?

ArrayList<Person> list = new ArrayList<Person>();

public void addPerson(Person p){
    if(list.size() == 0){
      list.add(p);
    } else{
      for(Person pp: list){
        int getIndex = list.indexOf(pp);
        int lOrder = p.getLastName().compareTo(pp.getLastName());
        if(lOrder > 0){
          list.add(getIndex + 1, p);
          break;
        } else if(lOrder == 0){
          int fOrder = p.getFirstName().compareTo(pp.getFirstName());
          if(fOrder > 0){
            list.add(getIndex, p);
            break;
          } else {
            list.add(getIndex + 1, p);
            break;
          }
        } else {
          list.add(getIndex, p);
          break;
        }
      }
    }
  }

3 个答案:

答案 0 :(得分:0)

很少有改进。

  • 如果您可以使用诸如 for(int i = 0; i < array.size(); i++)

  • 您不必分别检查lastNamefirstName。您可以将两者(p.lastName + p.firstName).compareTo(pp.lastName + pp.firstName)进行比较,然后对结果采取行动。由于已经有了当前元素的索引,因此只需检查是否只是将新项目插入相同的索引即可。

这是示例实现

static void addPerson(Person person) {
    for (int i = 0; i < sortedList.size(); i++) {
        var existingPerson = sortedList.get(i);
        var compareResult = compare(existingPerson, person);
        if (compareResult > 0) {
            sortedList.add(i, person);
            return;
        }
    }
    sortedList.add(person);
}

static int compare(Person p1, Person p2) {
    return (p1.lastName + p1.firstName).compareTo(p2.lastName + p2.firstName);
}

答案 1 :(得分:0)

代码的一个问题是,您要在循环的单次迭代之后进行插入,仅与列表中的第一个Person相比插入Person p。

这是一个改进的实现:

public void addPerson(Person person) {
    if (list.isEmpty()) {
        list.add(p);
    } else {
        // the position where you will insert the Person;
        // default value is list.size(), so it can be added to the end
        int position = list.size();

        Person p;
        for (int i = 0; i < list.size(); i++) {
            p = list.get(i);

            // if the comparison result is > 0, you found the first Person
            // in the list that comes alphabetically after;
            // Insert person before it, at position i
            if (compare(p, person) > 0) {
                position = i;
                break; // only break now that you've found the insert position
            }
        }
        list.add(person, position);
    }
}

/**
 * @return 0 if both Persons p1 & p2 have the same names, 
 *         a positive number if p1 is lexicographically greater than p2, 
 *         or a negative number if p1 is lexicographically less than p2 
 */
private int compare(Person p1, Person p2) {
    int result = p1.getLastName().compareTo(p2.getLastName());
    if (result == 0) {
        result = p1.getFirstName().compareTo(p2.getFirstName());
    }
    return result;
}

正如其他人所建议的那样,在可能的情况下在Person中实现Comparable接口也可以帮助创建更简洁的实现。

答案 2 :(得分:0)

算法的问题是,您总是查看目标列表中的第一个人,并且仅对该人做出决定,请注意所有“分支”的末尾都有一个break语句?

我了解您添加所有这些break语句的“原因”,这些确保新人总是在列表不匹配时插入列表,这与您首次检查列表是否为空的原因相同。 / p>

要正确实现“插入排序”系统,实际上您需要遍历列表的所有索引。

一个简单的“插入排序”算法如下所示:

  1. 遍历目标列表
  2. 检查现有条目是否比新条目“大”
  3. 如果现有条目更大,我们需要将该条目(所有其余所有条目)上移1个位置,插入条目,然后中止
  4. 如果完成循环,但在上述步骤中我们没有中止,请将我们的条目插入列表的末尾。
ArrayList<Person> list = new ArrayList<Person>();

public void addPerson(Person p){
    // Loop
    int size = list.size();
    for(int getIndex = 0; getIndex < size; getIndex++){
        Person pp = list.get(getIndex);
        // Compare
        int compare = p.getLastName().compareTo(pp.getLastName());
        if (compare > 0) {
            continue;
        } else if(compare == 0) {
            if (p.getFirstName().compareTo(pp.getFirstName()) > 0) {
                continue;
            }
        }
        // Add in existing slot
        list.add(getIndex, p);
        return;
    }
    // Add at the end
    list.add(p);
}

其中一个困难的部分是,我们必须对一个人进行两件事的比较,这使得比较逻辑的难度超出了需要。这可以通过将这部分分解为“辅助”比较器来解决,该比较器为我们完成此逻辑合并:

Comparator<Person> compare = Comparator
    .comparing(Person::getLastName)
    .thenComparing(Person::getFirstName);

// Then, inside the above loop:
        ...
        // Compare
        if (compare.compare(p, pp) > 0) {
            continue;
        }
        ...