Search code examples
javaalgorithmsortingmergesort

java array sort() manual realization


I have an array of objects, which have to be sorted by their fields. Sorting algorithm must be written manually. I've chosen merge sort, but can't understand, how to compare by different fields. Made classes with Comparator implementation, but don't understand, how to select which one has to be called.

Object class:

public class Ball{
    private int size;
    private int weight;
    private String color;

    public Ball(int size, int weight, String color) {
        this.size = size;
        this.weight = weight;
        this.color = color;
    }

    public int getSize() {
        return size;
    }

    public int getWeight() {
        return weight;
    }

    public String getColor() {
        return color;
    }

}

Comparator classes:

import java.util.Comparator;

public class SortByWeight implements Comparator<Ball> {

    @Override
    public int compare(Ball o1, Ball o2) {
        if(o1.getWeight()<o2.getWeight()){
            return -1;
        }
        if(o1.getWeight()==o2.getWeight()){
            return 0;
        }
        return 1;
    }
}
import java.util.Comparator;

public class SortByColor implements Comparator<Ball> {

    @Override
    public int compare(Ball o1, Ball o2) {
        return o1.getColor().compareTo(o2.getColor());
    }
}

Sorting algorithm class:

import java.util.Arrays;

public class TypeMergeSort {
    public static Ball[] mergeSort(Ball[] list){
        Ball[] buffer1 = Arrays.copyOf(list, list.length);
        Ball[] buffer2 = new Ball[list.length];
        Ball[] result = mergeSortInner(buffer1, buffer2, 0, list.length);
        return result;
    }
    public static Ball[] mergeSortInner(Ball[] buffer1, Ball[] buffer2, int startIndex, int endIndex) {
        if (startIndex >= endIndex - 1) {
            return buffer1;
        }

        //already sorted
        int middle = startIndex + (endIndex - startIndex) / 2;  //middle index
        Ball[] sorted1 = mergeSortInner(buffer1, buffer2, startIndex, middle);  //left part mergeSort recursion
        Ball[] sorted2 = mergeSortInner(buffer1, buffer2, middle, endIndex);    //right part mergeSort recursion

        //merge
        int index1 = startIndex;
        int index2 = middle;
        int destIndex = startIndex;

        Ball[] result = sorted1 == buffer1 ? buffer2 : buffer1;

        //in origin it was a code for int comparrison
        //select value to push
        while (index1 < middle && index2 < endIndex) {
            result[destIndex++] = sorted1[index1] < sorted2[index2]
                    ? sorted1[index1++] : sorted2[index2++];
        }
        //move left index
        while (index1 < middle) {
            result[destIndex++] = sorted1[index1++];
        }
        //move right index
        while (index2 < endIndex) {
            result[destIndex++] = sorted2[index2++];
        }

        return result;
    }
}

How should I fix it? Thx in advance


Solution

  • First, add a Comparator parameter to the merge sort functions.

    public static Ball[] mergeSort(Ball[] list, Comparator<Ball> comp){
        Ball[] buffer1 = Arrays.copyOf(list, list.length);
        Ball[] buffer2 = new Ball[list.length];
        Ball[] result = mergeSortInner(buffer1, buffer2, 0, list.length, comp);
        return result;
    }
    public static Ball[] mergeSortInner(Ball[] buffer1, Ball[] buffer2, int startIndex, int endIndex, Comparator<Ball> comp) {
        if (startIndex >= endIndex - 1) {
            return buffer1;
        }
        int middle = startIndex + (endIndex - startIndex) / 2;
        Ball[] sorted1 = mergeSortInner(buffer1, buffer2, startIndex, middle, comp); 
        Ball[] sorted2 = mergeSortInner(buffer1, buffer2, middle, endIndex, comp);
        // ...
    }
    

    Then, use Comparator#compare to find the relative ordering inside mergeSortInner.

    while (index1 < middle && index2 < endIndex) {
        result[destIndex++] = comp.compare(sorted1[index1], sorted2[index2]) < 0 ? sorted1[index1++] : sorted2[index2++];
    }
    

    Finally, create an instance of your custom Comparator when calling mergeSort.

    Ball[] sorted = mergeSort(arr, new SortByWeight());
    // this sorts the array by the weight field of each Ball
    

    You could also use the Comparator.comparing methods to define custom Comparators more succinctly.

    Ball[] sorted = mergeSort(arr, Comparator.comparingInt(Ball::getWeight));