简体   繁体   中英

How does Java's Collections.sort overwrite the List to be sorted

I'm writing a piece of code for a school asignment, we're implementing sorting algorithms but the algorithm works fine, I'm just having a little thought about why a line of code doens't work as I expect it to.

The calling code looks like this:

List<Integer> l = new LinkedList<Integer>();
l.add(new Integer(10));
l.add(new Integer(28));
l.add(new Integer(4));
l.add(new Integer(35));
l.add(new Integer(9));

ArraySort.sort(l);
System.out.println(l);

Collections.sort(l);
System.out.println(l);

I will put the code for our sort later on but the question is: How come Collections.sort overwrites the list with the new sorted list while ours does not?

The sort method works fine but simply doens't update the values of the list l in the calling class. I'm just curious as to how Collections does this, the solution would be to simply return a List from ArraySort.sort and do l = ArraySort.sort but that doesn't look as good!

Here is the code for the actual sorting:

public static void sort(List l) {
    mergeSort(l);
}

private static List mergeSort(List l) {
    if (l.size() <= 1) {
        return l;
    }
    List left = new LinkedList();
    List right = new LinkedList();
    int middle = l.size() / 2;
    for (int i = 0; i < middle; i++) {
        left.add(l.get(i));
    }
    for (int i = middle; i < l.size(); i++) {
        right.add(l.get(i));
    }

    left = mergeSort(left);
    right = mergeSort(right);

    l = merge(left, right);
    return l;
}

private static List merge(List left, List right) {
    List result = new LinkedList();
    while (left.size() > 0 || right.size() > 0) {
        if (left.size() > 0 && right.size() > 0) {
            if ((int) left.get(0) <= (int) right.get(0)) {
                result.add(left.get(0));
                left.remove(0);
            } else {
                result.add(right.get(0));
                right.remove(0);
            }
        } else if (left.size() > 0) {
            result.add(left.get(0));
            left.remove(0);
        } else if (right.size() > 0) {
            result.add(right.get(0));
            right.remove(0);
        }
    }
    return result;
}

Hope someone can clear this up for me.

It does not, it only changes the list content.

From the source :

 public static <T extends Comparable<? super T>> void sort(List<T> list) {
     Object[] a = list.toArray();
     Arrays.sort(a);
     ListIterator<T> i = list.listIterator();
     for (int j=0; j<a.length; j++) {
         i.next();
         i.set((T)a[j]);
     }
 }

You don't need to return a List object, but that doesn't make it wrong.

Note that you are assigning a new list to your list argument

l = merge(left, right);

Java passes by value, not by reference, hence it doesn't have any effect when you return from your method. You have to actually modify the list object passed to the method, not assign a new value to it.


Have you considered looking at the implementation in Java for comparison?

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java#Collections.sort%28java.util.List%29

The idea would be to change this:

l = merge(left, right);
return l;

into this (not sure if the order is preserved - I suppose it is):

l.clear();
l.addAll(merge(left, right)); //no need to return the list, it is the same

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM