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
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 Comparator
s more succinctly.
Ball[] sorted = mergeSort(arr, Comparator.comparingInt(Ball::getWeight));