优化java代码以缩短时间对array/arraylist进行排序

优化java代码以缩短时间对array/arraylist进行排序,java,arrays,arraylist,comparator,Java,Arrays,Arraylist,Comparator,我正在为一个测验编写一个程序,该程序要求我对一些数字进行排序并打印相应的字符串 为此,我创建了一个类Song,并获取了这个类的一个对象数组。我必须根据变量qi进行排序。问题是,根据法官的说法,我的解决方案耗时太多,效率不够。早些时候,我尝试了对象的ArrayList,并切换到可以在一定程度上优化它的数组思维,但没有任何帮助 如何进一步优化它 我的代码: class Song{ long fi; long qi; String si; public Song

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

为此,我创建了一个类
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;
    }
}   
class歌曲{
长fi;
龙琦;
串硅;
公歌(龙菲、弦丝、龙琦){
this.fi=fi;
this.si=si;
这个。气=气;
}
}
公共类Zipf{
公共静态void main(字符串[]args)
{
扫描仪扫描=新扫描仪(System.in);
长fi;
龙琦;
串硅;
int noOfSongs=scan.nextInt();
int selection=scan.nextInt();
List List=new ArrayList();//所有歌曲
树集=新树集(新树比较器());
for(int i=0;i民齐){
设置。移除(最小值);
设置。添加(歌曲);
min=set.first();
}
}
迭代器迭代器=set.degenerationIterator();
//显示树集数据

对于(int i=0;i,就大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();
    }
}

您也可以使用
TreeMap
,键为
qi
,值为
Song class
的对象,这样在创建时它就会被排序。如果排序是您的主要目的,那么就选择
TreeSet
,如果它需要经常获取数据,那么
ArrayList
是一个不错的选择

编辑


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

您的法官是否特别抱怨排序?这里我唯一的一点是不要创建
Long
对象并使用
Long.comparee(宋1.qi,宋2.qi)
取而代之。也许你没有发布代码中的其他内容?我尝试使用Long.compare,但我的eclipse显示错误。我代码中的其余部分只是根据此排序扫描输入和打印。有多少首歌曲需要判断/排序?最大限制为50000首。测验问题的确切措辞是什么?谢谢你的回答。我没有找到比较两个long的其他工作方法。在eclipse中使用long.compare会出现错误。我确实需要对元素进行排序!我必须按降序打印n个元素。n取自用户输入。通过减法进行比较会带来溢出风险。您编辑的代码非常有帮助。我将遵循此操作并重试。非常感谢。@assyli非常好的一点是,我去掉了减法。谢谢。@assylias很酷-我实际上在API文档中寻找了这个方法,但它不在那里…但现在我明白了,因为它是在1.7中添加的,我看了1.6(我不喜欢最近的API文档的外观和感觉,我认为该方法(如果有的话)从早期版本就已经存在了。)我需要根据qi进行排序,并为n(用户输入)打印si已排序的对象。使用它会更有效吗?请在这里添加哪个操作将发生更多的时间排序或打印。存储对象的数据结构只需要排序一次,然后在此基础上,首先要打印n个已排序对象的si。我希望我没有误解你的问题。是的,这是正确的我想知道的是。所以最好的选择是使用
ArrayList
public int compare(Song s1, Song s2) {
    if (s1.qi < s2.qi) return -1;
    if (s1.qi > s2.qi) return 1;
    return 0;
}