【问题标题】:Abstract Data Types, sorting objects by specific variable in a list抽象数据类型,按列表中的特定变量对对象进行排序
【发布时间】:2014-09-10 19:02:51
【问题描述】:

好的,我们开始吧。

我以 sortedArrayList 的形式创建了一个 ADT,它的 add 方法如下所示:

public boolean addToArray(T i)
    {


            int insertPlace = 0;

                for(int j=0;j<size;j++)
                { 

                    if(i.compareTo(sortedArray[j])<0)
                    {
                        insertPlace =j;
                        j = size;
                    }
                }
                if(size>0)
                {


                        for(int w=size-1; w>=insertPlace;w--)
                        {
                                sortedArray[size]=sortedArray[w];
                        }
                        sortedArray[insertPlace]=i;
                }
                else
                {
                    sortedArray[0]=i;
                }
                size++;



        return true;    


}

现在,当输入是字符串时,这对我的排序 ADT 产生了奇迹。但是,我想将对象添加到 Persons 形状的列表中,而不是字符串,该对象包含 4 个变量(字符串国家、字符串名称、整数年龄、整数 CPR)。我希望 Person 对象按年龄在列表中排序。

这是带有用于排序的 compareTo 方法的 Person 类。

public class Person implements Comparable<Person>
{
    int cpr=200193;
    int age=21;
    String name="John Doe";
    String Country="Uzbekistan";


    public Person() {
        this.cpr=cpr;
        this.age=age;
    }
    public Person(String name, String Country,int cpr,int age) 
    {
        this.cpr=cpr;
        this.age=age;
        this.name=name;
        this.Country=Country;
    }


    @Override
    public String toString()
    {
        return "Person [Country= " + Country + ", Name:" + name + ", Cpr: "+cpr+ ", age: "+age+"]";
    }

    public int compareTo(Person p)
    {
        int before=-1;
        int after=1;
        int middle=0;


        if(this.age!=p.age)
        {
            if(this.age>p.age) 
            {
                return before;
            } 

            if(this.age<p.age)
            {
                return after;
            }
        }
        return middle;
    }

现在,问题是对象被排序了,因为它们出现的顺序与我调用它们到列表中的顺序不同。我只是不知道它们是如何排序的,以及如何使列表中的对象按年龄排序。

编辑

p1.addToArray(new Person());
p1.addToArray(new Person("Pete","Germany",111111,86));
p1.addToArray(new Person("John","Denmark",123456,75));
p1.addToArray(new Person("Michael Jackson", "America",112345,49));

输出:

Item: Person [Country= America, Name:Michael Jackson, Cpr: 112345, age: 49]
Item: Person [Country= Uzbekistan, Name:John Doe, Cpr: 200193, age: 21]
Item: Person [Country= Germany, Name:Pete, Cpr: 111111, age: 86]
Item: Person [Country= Denmark, Name:John, Cpr: 123456, age: 75]

【问题讨论】:

  • 您可能会使用return Integer.compare(this.age, p.age) 而不是compareTo 方法中的所有行,但这只是在您找到问题所在之后。您是否尝试过使用 Collections.sort 而不是手动对列表进行排序?
  • 我们能看到排序错误的数组中有多个人的样子吗?
  • @MirMasej 是的,我会进行编辑,向您展示我添加的内容以及它的输出。
  • @Chronicle Collections.sort 不幸不是一个选项。

标签: java list generics abstract comparable


【解决方案1】:

我认为您的排序功能不起作用:

我的测试:

static void test() {
    addToArray("Zello");
    addToArray("Boby");
    addToArray("Amy");
    addToArray("Coco");
    addToArray("Boris");
    for(int i = 0; i < size; i++) {
        System.out.println(sortedArray[i]);
    }
}

输出:

Amy
Boris
Boby
Zello
Coco

这是一种不同且更有效的方法。

使用Arrays.binarySearch() 找到正确的插入位置。请注意,此函数返回:

  • 值的索引(如果已存在)。
  • -(insertPosition - 1) 如果值不存在。

根据您的代码,我假设size 变量表示数组中最后一个元素的索引。这意味着当数组为空时,您可能会将其初始化为 -1。

此外,我认为您不允许重复,并且每个 Person 都是唯一的,因此当您尝试插入重复项时,我的解决方案返回 false。

当然,请确保在匹配某些条件后调整数组的大小(通常是在数组半满时)。

public boolean addToArray(T item) {

    if (item == null) {
        return false;
    } else if (size == -1) {
        size++;
        sortedArray[size] = item;
        return true;
    } else {

        // find the correct insertion point using Binary Search
        int insertionPoint = Arrays
                .binarySearch(sortedArray, 0, size+1, item);

        if (insertionPoint >= 0) {
            // duplicate value
            return false;
        }

        // set the insertionPoint to proper value
        insertionPoint = (-(insertionPoint) - 1);

        // shift elements to the right of insertionPoint
        for (int i = size + 1; i > insertionPoint; i--) {
            sortedArray[i] = sortedArray[i - 1];
        }

        // insert at insertionPoint
        sortedArray[insertionPoint] = item;

        // update size
        size++;

        return true; //success
    }
}

此外,您还可以进一步简化 Person 对象中的 compareTo() 方法。

public int compareTo(Person p) {
    if(p != null) {
            return p.age - this.age;
    } else throw new NullPointerException();
}

现在,排序是降序的。如果要使其升序,请更改:

return p.age - this.age;

收件人:

return this.age - p.age;

这是full running example

示例输出(升序排序):

Person [Country= Uzbekistan, Name:John Doe, Cpr: 200193, age: 21]
Person [Country= America, Name:Michael Jackson, Cpr: 112345, age: 49]
Person [Country= Denmark, Name:John, Cpr: 123456, age: 75]
Person [Country= Germany, Name:Pete, Cpr: 111111, age: 86]

【讨论】:

  • 我试过了,不幸的是它不能解决问题。感谢您的快速回答。
  • 现在可以了,感谢周到的解释,从未使用过二进制搜索,但现在我看到了这样做的效率。
【解决方案2】:

要对 ArrayList 进行排序,您可以使用需要对其进行排序的类集合 import java.util.Collections; Collections.sort(yourArrayList);

方法sort需要你已经实现的类Person中的compareTo方法。

【讨论】:

  • 不幸的是,它不起作用,因为它是我自己用 实例化的数据类型。
猜你喜欢
  • 1970-01-01
  • 2015-01-03
  • 2021-01-25
  • 2012-06-26
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多