-3

I am trying to sort a string array for use in a list view. I have two string arrays one with the words I want to display, the other with the sort order I want. Any words that aren't in the sort list could be at the end. For Example:

String[] order = {"Paperclip", "Pencil", "Earphones", "Pen"};
String[] displaylist = {"Pencil 1", "Pen 1", "Dog 1", "Earphones 1", "Pen 2", "Paperclip 1", "Pencil 2", "Pen 3", "Earphones 2"};

The way I would want displaylist to be sorted afterward would be:

String[] displaylistsorted = {"Paperclip 1", "Pencil 1", "Pencil 2", "Earphones 1", "Earphones 1", "Earphones 2", "Pen 1", "Pen 2", "Pen 3", "Dog 1"}

I would like to be able to keep the list in the same Case after the sort.

I have looked through a lot of different tutorials and other Stack Questions for Custom Comparators, but my beginner level knowledge of Java ended up forcing me to write a question here.

Thanks so much for your help!

MJDude
  • 73
  • 10
  • Welcome to StackOverflow! Currently, your question is too broad - there are many possible ways to achieve what you want. A good way to narrow down your question would be to include something you have already tried - that way we can explain what parts need correction and why. – Mage Xy Jan 27 '16 at 22:06
  • I read in a lot of different places, but I couldn't find an example that matched what I was trying to do. I'm sorry it's too broad. Maybe next time I ask a question I will know more than what I do now. – MJDude Jan 27 '16 at 22:35

2 Answers2

0

You iterate over the set of words and compare them one by one with the array of search-terms. If you find a match, you add the word from the list to a lazy created list of matches for that term.

If you are through with the set, you join the result lists in the order of the search terms and add the remaining words at the end.

    List<String>[] results = new List[order.length];
    LinkedList<String> remainders = new LinkedList<String>();

    for (String word : displaylist) {
        boolean found = false;
        for(int i=0; i<order.length; i++) {
            if(word.contains(order[i])) {
                if(results[i] == null) results[i] = new LinkedList<String>();
                results[i].add(word);
                found = true;
                break;
            }
        }

        if( !found ) {
            remainders.add(word);
        }
    }

    List<String>theResult = new ArrayList<String>(displaylist.length);
    for ( List<String>result : results) {
        if( result != null ) theResult.addAll(result);
    }

    theResult.addAll(remainders);
thst
  • 4,592
  • 1
  • 26
  • 40
  • Thanks! but I got an error: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object[] java.util.Collection.toArray()' on a null object reference – MJDude Jan 27 '16 at 22:32
  • It will be helpful if you are more specific on where you found the error. Through the lazy list creation, not all elements of `results` are guaranteed to be non-null. The combination loop at the end requires a null check. I have added it. – thst Jan 27 '16 at 22:38
  • Thanks! That fixed it. Is this sure to include all of the items in the display list? – MJDude Jan 27 '16 at 22:52
  • What makes you think there is something missing? – thst Jan 27 '16 at 22:54
  • I have a very long list of items and I can't go through and check them all. Is there a possibility this doesn't include them all? or would it just add them to the end? – MJDude Jan 27 '16 at 22:58
  • If you debug the code with your sample list, you will see, that it neatly sorts each word into one of the possible lists. If no term matches, the word will be put into the remainders list. If you examine the assembly of `theResult`, you see, that all lists are combined. The remainders are added as the last part. You can compare the `size()` of the resulting list with your initial amount of data. That will be the same. – thst Jan 27 '16 at 23:05
0

You speak of custom comparators...directly comparing the contents of the arrays using String methods would probably be a more straightforward solution. However, for the purposes of academics, using a custom comparator means using a class to solve your problem. Creating a custom comparator in Java requires that you implement the Comparable interface. All this really means is that your class will need to implement the method compareTo method:

class MyClass implements Comparable {
   ...
   @Override
   public int compareTo(Object o) {
       ...
   }
}

When you override compareTo, you decide what makes an object "greater" or "less than" another object. If an object is "greater" than another object, your custom method should return 1. If it is "less than" another object, it should return -1. If it is equal, it should return 0. Being "greater" or "less than" indicates how objects should be sorted.

From what I can tell, the elements in your order array match the beginning of elements it would be called upon to help sort, e.g. "Paperclip 1" starts with "Paperclip". Assuming that is true, an appropriate compareTo method could use startsWith to make decisions about the appropriate order:

class MyClass implements Comparable {
    private static final String order[] = {"Paperclip", "Pencil", "Earphones", "Pen"};
    private String value;
    ...
    @Override
    public int compareTo(Object o) {
        MyClass that = (MyClass)o;
        int thisRank = 0;
        int thatRank = 0;
        for (String ord : order) {
            if (this.value.startsWith(ord)) {
                thisRank = count;
            }
            if (that.value.startsWith(ord)) {
                thatRank = count;
            }
            count++;
        }
        if (thisRank > thatRank) return 1;
        if (thisRank < thatRank) return -1;
        return 0;
    }
}

You would then need to create some kind of collection with your new class and then sort it:

MyClass displayList[] = { new MyClass("Pencil 1"), new MyClass("Pen 1"),
    new MyClass("Dog 1"), ... }
Arrays.sort(displayList);

or

TreeSet<MyClass> displayList = new TreeSet<>();
displayList.add(new MyClass("Pencil 1"));
displayList.add(new MyClass("Pen 1"));
...

Arrays.sort employs your compareTo method to properly sort the array. TreeSet does the same; it just calls compareTo every time you insert a new element.

Snapman
  • 601
  • 5
  • 11
  • Why create a class for each object? You could put your compare code into a `Comparator` object. – thst Jan 27 '16 at 23:17
  • I suppose that's true...the question mentioned comparators, so I just put together an example using classes. – Snapman Jan 29 '16 at 16:49