我尝试使用下面的代码根据年龄从最小到最年长重新排列我的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;
}
我做错了吗?或者是否有另一种根据特定变量排列对象数组的方法?
答案 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
循环中,您在i
(i > -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
的其他引用可能会看到其name
和age
发生变化。如果您交换对象的状态,那就不同于在数组中交换它们的位置。想象一下,你希望延长你的计划:现在人们可以结婚了。这意味着你举一个与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 )或二次时间中运行最坏情况。这意味着,在最坏的情况下,如果您将列表的长度加倍,则需要四倍的时间来解决问题。
计算机科学家提出了更好的方法来排序QuickSort和MergeSort。 MergeSort 例如在 O(n log n)中运行。这意味着如果您将列表的长度加倍,那么排序双倍所需的时间也会增加一个时间单位。那个时间单位是什么(一毫秒,纳秒,78秒......)是未知的,但最终,如果列表足够大, MergeSort 将胜过 InsertionSort 未列出的清单。
Java提供了大量的类,方法和算法。通过使用这些算法,您可以在如何完成错误安全,高效且没有太多/任何副作用的情况下进行大量研究。
为了执行错误安全和快速排序,您可以使用Arrays.sort(T[],IComparator<T>)
。