优化java代码以更少的时间对数组/ arraylist进行排序

时间:2013-12-25 09:14:05

标签: java arrays arraylist comparator

我正在编写一个测验程序,要求我对一些数字进行排序并打印相应的字符串。

为此,我创建了一个类Song,并获取了该类对象的数组。我必须在变量qi的基础上进行排序。问题在于,根据判断,我的解决方案需要花费太多时间并且效率不高。我之前尝试使用ArrayList个对象并切换到数组思维,可以在一定程度上优化它,但它没有任何帮助。

如何进一步优化?

我的代码:

   class Song{
    long fi;
    long qi;
    String si;

    public Song(long fi,String si, long qi){
        this.fi = fi;
        this.si = si;
        this.qi = qi;
    }
}

      public class Zipf {
    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);
        long fi;
        long qi;
        String si;
        int noOfSongs = scan.nextInt();
        int selection = scan.nextInt();
        List<Song> list=new ArrayList<Song>(); // all songs
        TreeSet<Song> set = new TreeSet<Song>(new treeComparator());
        for(int i=0; i< noOfSongs;i++)
        {
            fi=(scan.nextLong());
            si=(scan.next());
            qi=(fi*(i+1));
            list.add(new Song(fi,si,qi));//adding all songs to list
        }
        for(int i=0; i< selection;i++)
        {
            set.add(list.get(i));//adding no of songs to be selected into set

        }

        Song min = set.first();
        for (int i = selection; i < list.size(); i++) {
            Song song = list.get(i);
            if (song.qi > min.qi) {
                set.remove(min);
                set.add(song);
                min = set.first();
            }
        }
     Iterator<Song> iterator = set.descendingIterator();

                //Displaying the Tree set data
                for(int i=0;i<selection;i++){
                    System.out.println(iterator.next().si);
                }   

    }


}
class treeComparator implements Comparator<Song>{

    @Override
    public int compare(Song o1, Song o2) {
          if (o1.qi <= o2.qi) return -1;
            if (o1.qi > o2.qi) return 1;
            return 0;
    }
}   

2 个答案:

答案 0 :(得分:3)

就Big-O复杂性而言,您的解决方案是最佳的。如果你使用数组或ArrayList没关系,在两种情况下排序都需要O(nlogn)。

您可以在小范围内进行优化,例如避免在compare方法中创建新的丢弃对象。但从总体上看,这将对绩效产生微不足道的影响。

因此,您确定您对该任务的一般方法是否正确?我的意思是,你真的需要对列表进行排序吗?例如,如果任务只是找到最小qi,则可以不对整个列表进行排序。这可以推广到n最小qi这样:

List<Song> list; // all songs
int n; // provided by user

TreeSet<Song> set = new TreeSet<Song>(new Comparator() ...);
for (int i = 0; i < n; i++) {
    set.add(list.get(i));
}

Song max = set.last();
for (int i = n; i < list.size(); i++) {
    Song song = list.get(i);
    if (song.qi < max.qi) {
        set.remove(max);
        set.add(song);
        max = set.last();
    }
}

在这里,我们假设歌曲列表非常大,n小于列表中的歌曲数量。正如您所看到的,您不必对整个列表进行排序,只需线性迭代一次列表就足够了,并且只对输出集进行排序。

Comparator与您在自己的代码中使用的相同,但如果您“手动”进行比较,则可以不使用new Long

public int compare(Song s1, Song s2) {
    if (s1.qi < s2.qi) return -1;
    if (s1.qi > s2.qi) return 1;
    return 0;
} 

答案 1 :(得分:0)

您还可以使用TreeMap,密钥为qi,值为Song class的对象。因此它将在创建时进行排序。如果排序是您的主要目的,那么请转到TreeSet,如果需要经常获取数据,那么ArrayList是不错的选择。

修改

具有预定ArrayList

max size更快,因为它减少了增量重新分配的数量。因此,如果您知道最多歌曲数量,那么这将更快。