0
\$\begingroup\$

I am trying to sort a list on basis of C before .

Is there better way to do this?

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class MainClass {
    public static void main(String args[]) {

    List<String> activeLoadList = new LinkedList<String>();
    List<String> tempList = new LinkedList<String>();
    activeLoadList.add("REL1110C.PZ");
    activeLoadList.add("REL1110Z.PS");
    activeLoadList.add("REL1110C.AB");
    activeLoadList.add("REL1110Z.CD");
    activeLoadList.add("REL1110C.OP");

    System.out.println("Queue is ***" + activeLoadList);

    Iterator<String> iter = activeLoadList.iterator();
    while (iter.hasNext()) {
        String next = iter.next();
        if (next.contains("C.")) {
            iter.remove();
            tempList.add(next);
        }
    }

    activeLoadList.addAll(tempList);
    System.out.println("Queue is ***" + activeLoadList);
  }
}

Output:

Queue is ***[REL1110C.PZ, REL1110Z.PS, REL1110C.AB, REL1110Z.CD, REL1110C.OP]

Queue is ***[REL1110Z.PS, REL1110Z.CD, REL1110C.PZ, REL1110C.AB, REL1110C.OP]

\$\endgroup\$
  • \$\begingroup\$ I'm not sure I get the question. Do you want to maintain the intial order but the "C." at the end? \$\endgroup\$ – Francesco Pitzalis Mar 17 '16 at 10:12
  • \$\begingroup\$ Yes, I want to sort term in order such that all term having C.* shall come in end. \$\endgroup\$ – Batty Mar 17 '16 at 11:36
7
\$\begingroup\$

Instead of modifying the structure of the list (adding, removing) you should rather use a Comparator (see the javadoc), which in your case could look like this:

Collections.sort(activeLoadList, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        boolean aContainsPattern = a.contains("C.");
        boolean bContainsPattern = b.contains("C.");
        if (aContainsPattern == bContainsPattern){
            return 0;
        } else {
            return aContainsPattern ? 1 : -1;
        }
    }
});

Note though, that you could/should extract your pattern to a constant instead of having it duplicated (like in my example) and furthermore, that you could use a lambda instead of an anonymous inner class if you use Java 8.

Edit:

In case you use Java 8 (and the ternary operator ?) you could boil that down quite a bit:

final String p = "C."; // the pattern to search for
Collections.sort(activeLoadList, (a, b) -> (a.contains(p) == b.contains(p) ? 0 : (a.contains(p) ? 1 : -1)));

But for the sake of readability you may rather use the more verbose version. Furthermore Solomonoff's Secret's solution is to prefer in case you won't have any further sorting criteria in the future. If you may have additional ones, though, a Comparator may be the easier way to go.

Edit 2:

As has been pointed out by Solomonoff's Secret this could even be simplified further with Java 8's Comparator.comparing:

Collections.sort(activeLoadList, Comparator.comparing(text -> text.contains("C.")));

Edit 3:

Thanks to Fabio F. for an even short version using Java 8:

activeLoadList.sort(Comparator.comparing(text -> text.contains("C.")));
\$\endgroup\$
  • \$\begingroup\$ I believe your second example can be simplified using Collections.sort(activeLoadList, Comparator.comparing(text -> text.startsWith("C."))), which would make your sorting much shorter than my answer. It would also IMO be much more readable than my answer. \$\endgroup\$ – Reinstate Monica Mar 18 '16 at 0:56
  • \$\begingroup\$ I suppose that the condition expression aContainsPattern && bContainsPattern should be aContainsPattern == bContainsPattern – if I get the problem correctly, two items are equal when both have "C." substring or when neither has it. \$\endgroup\$ – CiaPan Mar 18 '16 at 10:21
  • \$\begingroup\$ In Java 8 List have sort method so you could just write: activeLoadList.sort(Comparator.comparing(text -> text.contains("C."))); \$\endgroup\$ – Fabio F. Mar 18 '16 at 15:23
4
\$\begingroup\$

Philonous's answer solves this problem in O(n * log(n)) time. This answer will solve it in O(n) time, albeit with a bit more code than in the other answer. Note that in this case performance might not matter; however, it could matter if you were to scale up to millions of items. This answer requires Java 8.

    final List<String> unsorted = ...
    final Predicate<String> startsWithCDot = str -> str.startsWith("C.");
    final List<String> sorted = Stream.concat(
        unsorted.stream().filter(startsWithCDot.negate()),
        unsorted.stream().filter(startsWithCDot)
    ).collect(Collectors.toList());
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.