tags:

views:

147

answers:

4

I have a String list:

List<String> listString  = new ArrayList<String>();
listString.add("faq");
listString.add("general");
listString.add("contact");

I do some processing on the list and I want to sort this list but I want "general" to always end up in first position. Thx ;)

+10  A: 

Sort the list without having "general" inside it and then add it to the beginning.

Petar Minchev
Terrible hack. Use `subList` instead, see my answer.
polygenelubricants
@poly, I disagree strongly that this is a "terrible hack". It's very straight forward and works.
Paul Tomblin
@Paul: it's terrible because it makes unnecessary structural modification (remove then add).
polygenelubricants
@poly, that would depend very much on whether this list is built once or multiple times. If it were only built once, then it's reasonable to add everything except "general", sort it, then add "general" to the front. It it were built multiple times, or modified after it were built, then yes, that's a bad choice.
Paul Tomblin
+4  A: 

Do Collections.sort on its subList instead.

    List<String> list = new ArrayList<String>(
        Arrays.asList("Zzz...", "Two", "One", "Three")
    );
    Collections.sort(list.subList(1, list.size()));
    System.out.println(list);
    // "[Zzz..., One, Three, Two]"

API links

  • subList(int fromIndex, int toIndex)
    • Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.

If the special element is not at index 0, then simply put it there before you sort it as follows:

    List<String> list = new ArrayList<String>(
        Arrays.asList("Four", "Five", "Zzz...", "Two", "One", "Three")
    );
    Collections.swap(list, list.indexOf("Zzz..."), 0);
    Collections.sort(list.subList(1, list.size()));
    System.out.println(list);
    // "[Zzz..., Five, Four, One, Three, Two]"

API links

polygenelubricants
@Petar: see example.
polygenelubricants
Yeah, but in his example "Zzz..." was at second position:)
Petar Minchev
I mean who said it will be always on first position as in your example code.
Petar Minchev
@Petar: that's why question needs clarification. My answer is how to sort elements of a list except the first. That is, how to sort the `subList(1,...)` of a `List`.
polygenelubricants
I actually think this is less readable than Petar's answer. In his answer it's very clear that the first item is a special case, and it's very explicit that "General" should be on top. This is undoubtedly better if you don't know what the first element will be, but otherwise I'd go for the explicit solution.
extraneon
@Petar test it. It works perfectly, assuming that the "general" is actually first, as the OP's question states (but the code doesn't show)
CPerkins
and if general is not the first how to do to sort this list and put general in first position ?
Mercer
@extraneon: and in this answer it's very clear that you're sorting the `subList(1,...)` of a `List`. That is, you're sorting every elements but the first. It doesn't get any more readable than this. Whether or not this is what OP needs is unclear due to the `"general"` issue.
polygenelubricants
@CPerkins Where did I say poly's suggestion doesn't work if the element is in first position?
Petar Minchev
@Petar you asked how it would work. Oh, you edited your comment. Okay then.
CPerkins
@Mercer: see latest revision.
polygenelubricants
+3  A: 

I like @Petar's approach, but another approach would be to sort it using a custom Comparator that always said that "general" was before whatever it was being compared to.

Collections.sort(list, new Comparator<String>()
  {
     int compare(String o1, String o2)
     {
         if (o1.equals("general"))
           return -1;
         if (o2.equals("general"))
           return 1;
         return o1.compareTo(o2);
     }
});
Paul Tomblin
yes i just post an example but how to using a comparator that always said that "general" was before whatever ?
Mercer
Do a specific `if`-statement first thing in the compare method, that checks if one of the inputs equal "general".
aioobe
Actually, this might not be stable, depending on the algorithm used by Collections.sort, so you may want to test o1 and o2 for equality before comparing them to "general".
Paul Tomblin
+1  A: 

You can use the following code snippet but it might have perfomance/memory problems for the very big lists.

public static List<String> sortSpecial(List<String> list, final String alwaysOnTopItem) {
    list.remove(alwaysOnTopItem);
    Collections.sort(list);

    List<String> result = new ArrayList<String>(list.size() + 1);
    result.add(alwaysOnTopItem);
    result.addAll(list);

    return result;
}

public static void main(String[] args) {
    List<String> listString = new ArrayList<String>();
    listString.add("faq");
    listString.add("general");
    listString.add("contact");
    String alwaysOnTopItem = "general";
    List<String> sortedList = sortSpecial(listString, alwaysOnTopItem);
    System.out.println(sortedList);
}