重新排列数组 - java

时间:2015-12-15 14:38:45

标签: java arrays

我尝试使用下面的代码根据年龄从最小到最年长重新排列我的Person数组。

public class Trial {

    public static void main(String[] args){

        Person[] person = new Person[3];

        person[0] = new Person("Jerome", 21);
        person[1] = new Person("Jam", 16);
        person[2] = new Person("Imelda", 53);

        for(int i=0; i<person.length;i++){
            System.out.println(person[i].getName() + " " + person[i].getAge());
        }

        String name = "";
        int age = 0;
        int counter = 0;

        for(int i=1;i<person.length;i++){

            name = person[i].getName();
            age = person[i].getAge();

            counter = i - 1;

            while(i>-1&&person[counter].getAge()>age){
                person[counter+1].setAge(person[counter].getAge());
                person[counter+1].setName(person[counter].getName());
                counter -= 1;
            }


            person[counter+1].setAge(age);
            person[counter+1].setName(name);

        }

        for(int i=0; i<person.length;i++){
            System.out.println(person[i].getName() + " " + person[i].getAge());
        }

    }
}

算法可以使用整数数组顺利运行,但在这里,我得到了这个错误。

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at com.example.java.Trial.main(Trial.java:28)

这是错误指向

的地方
while(i>-1&&person[counter].getAge()>age){
                person[counter+1].setAge(person[counter].getAge());
                person[counter+1].setName(person[counter].getName());
                counter -= 1;
            }

我做错了吗?或者是否有另一种根据特定变量排列对象数组的方法?

3 个答案:

答案 0 :(得分:5)

如果您Person实施Comparable,则可以Arrays.sort(...)为您执行此操作!

public class Person implements Comparable<Person> {
    // Existing class implementation

    @Override
    public int compareTo(Person p) {
        return p2.age - this.age;
    }
}

编辑或者,您可以在调用compareTo时直接内联实施Arrays.sort()方法(即:不需要修改Person):< / p>

Arrays.sort(personArray, new Comparator<Person>() {
    @Override
    public int compare(Person p1, Person p2) {
        return p2.age - p1.age;
    }
});

如果您正在运行Java 8,则可以使用lambda表达式进一步缩短它:

Arrays.sort(personArray, (p1, p2) -> p2.age - p1.age);

答案 1 :(得分:0)

尝试改变这一点:

     for(int i=1;i<person.length;i++){

     for(int i=1;i<=person.length;i++){ 

答案 2 :(得分:0)

核心问题确实存在于那里:

while(i>-1&&person[counter].getAge()>age){
    person[counter+1].setAge(person[counter].getAge());
    person[counter+1].setName(person[counter].getName());
    counter -= 1;
}

while循环中,您在ii > -1)上执行边界检查,但您使用的是counter。因此,为了解决核心问题,您使用counter代替i

while(counter>-1&&person[counter].getAge()>age){
    person[counter+1].setAge(person[counter].getAge());
    person[counter+1].setName(person[counter].getName());
    counter -= 1;
}

然而,这不是对数组中的对象进行排序的好方法。由于以下几个原因:

  • 您可以交换这些对象的状态,而不是交换对象。想象一下,在项目的后期,您必须向Person添加一个新字段,然后您的算法就会被破坏。此外,对Person的其他引用可能会看到其nameage发生变化。
  • 您正在实施插入排序算法,而QuickSortMergeSort显着优于insertion sort

交换状态的问题

如果您交换对象的状态,那就不同于在数组中交换它们的位置。想象一下,你希望延长你的计划:现在人们可以结婚了。这意味着你举一个与Bob结婚的Person某个数组。说鲍勃和爱丽丝结婚了。如果稍后你将Bob的名字修改为Cindy,那么Cindy就会与Alice结婚。

您可以通过将代码重写为:

来解决该问题
for(int i=1;i<person.length;i++) {
    Person toSwap = person[i];
    counter = i - 1;
    while(counter >-1 &&person[counter].getAge()>age) {
        person[counter+1] = person[counter];
        counter -= 1;
    }
    Person[counter+1] = toSwap;
}

此外,建议在while中转换for,因为产生无限循环的可能性较小:

for(int i=1;i<person.length;i++) {
    Person toSwap = person[i];
    for(counter = i-1; counter >-1 &&person[counter].getAge()>age; counter--) {
        person[counter+1] = person[counter];
    }
    Person[counter+1] = toSwap;
}

排序算法

您基本上实现了insertion sort的版本。插入排序采用一个对象,查找所有较大(或较小)的对象,将这些对象向右移动一个(左),然后将对象定位在正确的位置。这在 O(n 2 二次时间中运行最坏情况。这意味着,在最坏的情况下,如果您将列表的长度加倍,则需要四倍的时间来解决问题。

计算机科学家提出了更好的方法来排序QuickSortMergeSort MergeSort 例如在 O(n log n)中运行。这意味着如果您将列表的长度加倍,那么排序双倍所需的时间也会增加一个时间单位。那个时间单位是什么(一毫秒,纳秒,78秒......)是未知的,但最终,如果列表足够大, MergeSort 将胜过 InsertionSort 未列出的清单。

使用内置

Java提供了大量的类,方法和算法。通过使用这些算法,您可以在如何完成错误安全,高效且没有太多/任何副作用的情况下进行大量研究。

为了执行错误安全快速排序,您可以使用Arrays.sort(T[],IComparator<T>)