简体   繁体   中英

Java: How to create a sorted string ArrayList based on Custom object ArrayList without using Sort()

I have a class called Word in which each instance has String , ArrayList<Character> , and a double . Let's say there are 3 instances of this class. I would like to create a new ArrayList<String> in which all 3 word strings are contained. However, the order of the Strings must go from high to low of the doubles from their original instances. The major stipulation of this project is that the Collections.sort method cannot be used. Please see the code below and let me know if you can think of a way to write this loop (a loop is needed because there is actually +50,000 words):


import java.awt.List;
import java.util.ArrayList;
import java.util.Arrays;


public class WordRecommender {

    String fileName;

    public WordRecommender(String fileName) {
        this.fileName = fileName;
    }

    public static void main(String[] args) {

    ArrayList<Word> objectArray = new ArrayList<Word>();

    objectArray.add(new Word("people", null ,0.8));
    objectArray.add(new Word("dogs", null ,0.4));
    objectArray.add(new Word("cats", null ,0.6));

    ArrayList<String> outputArray = new ArrayList<String>();

    for (int i = 0; i < finalArray.size(); i++) {
      // code here to find the value of each double and place the 
      // associated strings into output Array from highest to lowest
    }

    // ideal outputArray order = ["people", "cats", "dogs"]

}
import java.util.ArrayList;

public class Word {

    String wordName;
    ArrayList<Character> uniqueLetters;
    double percent;

    public Word(String string, double percent) {
        ArrayList<Character> tempArray = new ArrayList<Character>();

        for (int i = 0; i < string.length(); i++) { 
            tempArray.add(string.charAt(i));
        }

        this.wordName = string;
        this.uniqueLetters = tempArray;
        this.percent = percent;
    }

}

The result you need to achieve can be broken in 2 major steps:

  1. Describing how, giving 2 Word s, which of them will be put before the other in the List
  2. Using the comparing method to actually sort your list of Word s.

Step 1: How can we decide which word comes first?

Java has an interface called Comparable . The name is pretty self-explanatory. When you implement this interface in your Word class, you are telling Java that instances of this class can be compared against each other.

public class Word implements Comparable<Word>{

When you edit this line in your Word class, your IDE will probably complain about a "missing compareTo() method". The compareTo() method is defined in the Comparable interface and its job is deciding, from 2 instances, which one should be considered "larger" (or in our case, should be put first in the List ).

An example of a usage is: "apple".compareTo("banana"); . This method call should return a positive number if the first instance ("apple") is "larger", a negative number if the second instance ("banana") is "larger", or zero if both are of the same "value". By the way, the compareTo() method implemented by String s in Java evaluates instances by alphabetical order.

So let's implement our version of the compareTo() method for our Word class.

@Override
public int compareTo(Word anotherWord) {
    if(this.percent > anotherWord.percent) {
        return 1;
    } else if (this.percent < anotherWord.percent) {
        return -1;
    } else {
        return 0;
    }
}

Keep in mind that this implementation returns a positive value if the first instance is greater than the second, and a negative value in the other way around.

Now that we have a way of comparing our Words , we can move on to the sorting part.

Step 2: Sorting algorithms

There are a huge variety of sorting algorithms available on the internet. Some are less efficient, some are easier to implement. You can research some of them here .

For me, the easiest sorting algorithm is called BubbleSort . It is not very efficient, though.

ArrayList<Word> objectArray = new ArrayList<Word>();

objectArray.add(new Word("people", 0.8));
objectArray.add(new Word("dogs", 0.4));
objectArray.add(new Word("cats", 0.6));

for(int i = 0; i < objectArray.size() - 1; i++) {
    for(int j = 0; j < objectArray.size() - i - 1; j++) {
        // Remember: a compareTo() call returning a negative number
        // means that the first instance is smaller than the second.
        if(objectArray.get(j).compareTo(objectArray.get(j + 1)) < 0) {
            Word auxiliary = objectArray.get(j);
            objectArray.set(j, objectArray.get(j + 1));
            objectArray.set(j + 1, auxiliary);
        }
    }
}

These two nested for loops will sort objectArray in descending order of percent .

I implemented a solution that involves a sorting algorithm and usage of java.util.Comparable both.

First, you need to implement Word class with java.util.Comparable so that you can define how to compare Word class in order to determine which one is greater or lower than the other. In this case, it will be the percent field.

public class Word implements Comparable<Word> {

    String wordName;
    ArrayList<Character> uniqueLetters;
    double percent;

    public Word(String string, double percent) {
        ArrayList<Character> tempArray = new ArrayList<Character>();

        for (int i = 0; i < string.length(); i++) {
            tempArray.add(string.charAt(i));
        }

        this.wordName = string;
        this.uniqueLetters = tempArray;
        this.percent = percent;
    }

    @Override
    public int compareTo(Word o) {
        // It is better to delegate to built-in Double compare 
        // because all we need to compare doubles
        return Double.compare(this.percent, o.percent);
    }

    @Override
    public String toString() {
        return this.wordName;
    }

}

Second, the most important part is to implement a sorting algorithm. It can be challenging to implement them on your own so I suggest study them first.

For my solution it will be a regular implementation of Quick Sort algorithm as follows:

public class QuickSort {

    private Word[] array;

    public QuickSort(Word... words) {
        this.array = words;
    }

    public Word[] sort(){
        this.sort(this.array, 0, this.array.length-1);
        return this.array;
    }

    private void sort(Word[] array, int begin, int end) {

        //exit condition
        if (begin >= end)
            return;

        Word pivot = array[end];
        int sortIndex = begin;

        for (int i = begin; i < end; i++) {
            // instead of > we use compareTo to externalize comparison logic 
            // greater than (>) means we sort in descending order  
            if (array[i].compareTo(pivot) > 0) {
                Word swap = array[sortIndex];
                array[sortIndex] = array[i];
                array[i] = swap;
                sortIndex++;
            }
        }
        //placing pivot to the sort index
        Word swap = array[sortIndex];
        array[sortIndex] = pivot;
        array[end] = swap;

        this.sort(array, begin, sortIndex-1);
        this.sort(array, sortIndex+1, end);

    }

}

Finally, you just use QuickSort helper class to sort your collection of Word and get the sorted output:

public class WordRecommender {

    String fileName;

    public WordRecommender(String fileName) {
        this.fileName = fileName;
    }

    public static void main(String[] args) {

        ArrayList<Word> objectArray = new ArrayList<Word>();

        objectArray.add(new Word("people" ,0.8));
        objectArray.add(new Word("dogs", 0.4));
        objectArray.add(new Word("cats" ,0.6));

        QuickSort quickSort = new QuickSort(objectArray.toArray(new Word[]{}));
        Word[] sortedWordArray = quickSort.sort();

        //output: [people, cats, dogs]
        System.out.println(Arrays.asList(sortedWordArray));

    }

}

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