If I have an ArrayList as the following:
["a 100", "b 32", "t 54", "u 1"] (numbers and letter are separated by space in each cell of the array list).
How can I sort it by numbers keeping each number with its corresponding letter?.
This looks like you are trying to implement object oriented programming using strings. Luckily, Java has already done this.
So, do something like this instead:
public class MyClass implements Comparable<MyClass> {
private final String aString; //could be char perhaps..
private final Integer anInteger;
public MyClass(final String aString, final Integer anInteger) {
this.aString = aString;
this.anInteger = anInteger;
}
public String getAString() { return aString; }
public Integer getAnInteger() { return anInteger; }
public String toString() { return anInteger + " " + aString }
//comparison by number
public int compareTo(final MyClass other) {
return anInteger.compareTo(other.anInteger);
}
}
Then, you use it like this:
final List<MyClass> myClasses = new ArrayList<>();
myClasses.add(new MyClass("a", 100));
myClasses.add(new MyClass("b", 32));
myClasses.add(new MyClass("t", 54));
myClasses.add(new MyClass("u", 1));
Collections.sort(myClasses);
You can simply use swapping method just like in regular arrays. The only difference is that we use set(index, "value") method to update a specific string at specified index.
public static void sort (ArrayList<String> arr){
int N = arr.size();
int E = N-1;
String temp;
boolean flag = true;
while(flag){
flag=false;
for(int a = 0 ; a < E ; a++){
if(Integer.parseInt(arr.get(a).substring(arr.get(a).indexOf(" ")+1)) >
Integer.parseInt(arr.get(a+1).substring(arr.get(a+1).indexOf(" ")+1))) {
temp=arr.get(a);
arr.set(a, arr.get(a+1));
arr.set(a+1, temp);
flag=true;
}
}
E--;
}}
The sorting algorithm is bubble sort. I have used it due to simplicity. You can use any other sorting algorithm if you want.
Then, you can call the sort() function in main method:
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<String>();
arr.add("a 98");
arr.add("a 23");
arr.add("c 11");
sort(arr);
}
Use a custom comparator to sort the list.
List<String> yourList = Arrays.asList("a 100", "b 32", "t 54", "u 1");
yourList.sort((entry1, entry2) -> {
int number1 = Integer.parseInt(entry1.split(" ")[1]);
int number2 = Integer.parseInt(entry2.split(" ")[1]);
return Integer.compare(number1, number2);
});
Regards
import static java.lang.Integer.*;
Just import static Integer methods and you'll get the most compact Comparator<String> for your purpose.
(a, b) -> compare(valueOf(a.split(" ")[1]), valueOf(b.split(" ")[1]));
Assuming the elements in the list are the same pattern:
then you can do
public static void main(String[] args) {
// ["a 100", "b 32", "t 54", "u 1"]
List<String> myList = new ArrayList<>();
myList.add("a 100");
myList.add("b 32");
myList.add("t 54");
myList.add("u 1");
System.out.println("List unsorted" + myList);
Collections.sort(myList, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
try {
int a1 = Integer.parseInt(o1.substring(2));
int a2 = Integer.parseInt(o2.substring(2));
return Integer.compare(a1,a2);
} catch (NumberFormatException ex) {
return 0;
}
}
});
System.out.println("List sorted" + myList);
}
In Java 8, Comparator has a handful of static and default methods that make it easy to create custom comparators. For instance, you could create one that splits each string and converts the second word to an integer.
list.sort(Comparator.comparingInt(
s -> Integer.parseInt(s.split(" ")[1])
));
Related
I am trying to solve the problem at https://leetcode.com/problems/design-a-food-rating-system and this is my solution.
class FoodRatings {
class SortedSetComparator implements Comparator<String> {
public int compare(String A, String B) {
if (foodRatingMap.get(A) == foodRatingMap.get(B)) {
return A.compareTo(B);
}
return foodRatingMap.get(B).compareTo(foodRatingMap.get(A));
}
}
Map<String, SortedSet<String>> foodTypeMap;
Map<String, String> foodMap;
Map<String, Integer> foodRatingMap;
public FoodRatings(String[] foods, String[] cuisines, int[] ratings) {
foodTypeMap = new HashMap<>();
foodMap = new HashMap<>();
foodRatingMap = new HashMap<>();
for (int i = 0; i<foods.length; i++) {
foodTypeMap.putIfAbsent(cuisines[i], new TreeSet<String> (new SortedSetComparator()));
foodMap.put(foods[i], cuisines[i]);
foodRatingMap.put(foods[i], ratings[i]);
foodTypeMap.get(cuisines[i]).add(foods[i]);
}
}
public void changeRating(String food, int newRating) {
foodRatingMap.put(food, newRating);
SortedSet<String> set = foodTypeMap.get(foodMap.get(food));
if (!set.remove(food)) {
System.out.println("Unable to find " + food);
}
foodTypeMap.get(foodMap.get(food)).add(food);
}
public String highestRated(String cuisine) {
return foodTypeMap.get(cuisine).first();
}
}
Could anyone tell me why the TreeSet remove() method is not working ?
Here is the input for the same.
public static void main(String args[]) {
String[] foods = new String[] {
"czopaaeyl", "lxoozsbh", "kbaxapl"
};
String[] cuisines = new String[] {
"dmnuqeatj", "dmnuqeatj", "dmnuqeatj"
};
int[] ratings = new int[] {
11, 2, 15
};
FoodRatings obj = new MyClass().new FoodRatings(foods, cuisines, ratings);
obj.changeRating("czopaaeyl", 12);
String food = obj.highestRated("dmnuqeatj");
System.out.println(food);
obj.changeRating("kbaxapl", 8);
food = obj.highestRated("dmnuqeatj");
System.out.println(food);
obj.changeRating("lxoozsbh", 5);
food = obj.highestRated("dmnuqeatj");
System.out.println(food);
}
I am not sure why the remove function is not working properly here.
Well, it took me a while to find the problem. Besides the Integer compare issue which is only needed to sort equal ratings in lexical order. You were updating the ratings prior to doing a remove. But since your set uses this structure in its comparator, things got out of sync.
public void changeRating(String food, int newRating) {
SortedSet<String> set = foodTypeMap.get(foodMap.get(food));
if (!set.remove(food)) {
System.out.println("Unable to find " + food);
}
foodTypeMap.get(foodMap.get(food)).add(food);
foodRatingMap.put(food, newRating);
}
As soon as I moved foodRatingMap.put(food, newRating); to the bottom, it worked. BTW, I would have written a Food class hold each foods type, rating, and cuisine. Usually these test sites are only interested in results and efficiency, not how you did it.
Well. That was a very subtle issue to find. First the order in which the ratings were updated are wrong. The correct order was :-
Remove the food from the sortedSet.
Update the rating.
Add the food back to the sorted set.
Changes were done in two places.
The first one was to correct the order.
public void changeRating(String food, int newRating) {
foodTypeMap.get(foodMap.get(food)).remove(food);
foodRatingMap.put(food, newRating);
foodTypeMap.get(foodMap.get(food)).add(food);
}
The second one was to use equals() when comparing integer values in the comparator.
class SortedSetComparator implements Comparator<String> {
public int compare(String A, String B) {
if (foodRatingMap.get(A).equals(foodRatingMap.get(B))) {
return A.compareTo(B);
}
return foodRatingMap.get(B).compareTo(foodRatingMap.get(A));
}
}
I am trying to solve a exorcise that is supposed to learn me about the Comparable<T> interface. It tells me to find the shortest and longest string in a string array.
I think I am supposed to make my own compareTo() -method because the String.compareTo() method sorts alphabetically. But I can't get what my method should look like.
This is my code so far:
class ComparableTest implements Comparable<String> {
public static void main(String[] args) {
String arr[] = {"hei", "hvordan", "gaar", "det", "med", "deg", "a"};
String tempSto = arr[0]; //long string
String tempLit = arr[0]; //short string
for(String e : arr) {
if(e.compareTo(tempSto) > 0) {
tempSto = e;
}
if(e.compareTo(tempLit) < 0) {
tempLit = e;
}
}
System.out.println("Longest string is: " + tempSto);
System.out.println("Shortest string is: " + tempLit);
}
}
As you mentioned, you should implement your own Comparator, based on the String's length, not its alphabetical contents. E.g.:
public class StringLengthComparator extends Comparator<String> {
#Override
public int compare (String s1, String s2) {
return Integer.compare(s1.length(), s2.length();
}
}
Once you've done that, you can use it to find the shortest string in the array, or just reuse Collections#min(Collection, Comparator) to do the heavy lifting for you:
String shortest =
Collections.min(Arrays.asList(arr), new StringLengthComparator());
If your class implements the Comparable interface, i guess you have to override the compareTo method, and compare the length of the two String compared.
You can use a comparable to sort a list according to your own needs. This means in your case, that the highest and lowest number of characters in a string is relevant for the comparing. So, you subtract those value from each other in the comparing function. If you have for example house and dog, you have the two values 5 and 3. By subtracting the values from each other, you get the difference on how close those values are. So, just return the difference of the length of the two parameters in your ordering function. The first and last element in the list will then be the largest and smallest word (depending on which value you subtract from which).
In Java 8:
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
String arr[] = {"hei", "hvordan", "gaar", "det", "med", "deg", "a"};
String minLengthStr = Arrays.stream(arr)
.min((str1, str2) -> Integer.compare(str1.length(), str2.length()))
.get();
String maxLengthStr = Arrays.stream(arr)
.max((str1, str2) -> Integer.compare(str1.length(), str2.length()))
.get();
System.out.println("Longest string is: " + maxLengthStr);
System.out.println("Shortest string is: " + minLengthStr);
}
}
Output:
Longest string is: hvordan
Shortest string is: a
Explanation:
The min method in the Stream class takes a Comparator as a parameter. As Comparator is a functional interface we can use a lambda expression as a short hand for implementing it.
So instead of writing:
Comparator<String> lengthComparator = new Comparator<String>() {
#Override
public int compare(String str1, String str2) {
return Integer.compare(str1.length(), str2.length());
}
};
You can write:
Comparator<String> lengthComparator = (str1, str2) -> Integer.compare(str1.length(), str2.length());
You can use this without streams too:
public class Example {
public static void main(String[] args) {
String arr[] = {"hei", "hvordan", "gaar", "det", "med", "deg", "a"};
String minLengthStr = arr[0], maxLengthStr = arr[0];
Comparator<String> lengthComparator = (str1, str2) -> Integer.compare(str1.length(), str2.length());
for(String str : arr) {
if(lengthComparator.compare(str, minLengthStr) == -1) {
minLengthStr = str;
} else if(lengthComparator.compare(str, maxLengthStr) == 1) {
maxLengthStr = str;
}
}
System.out.println("Longest string is: " + maxLengthStr);
System.out.println("Shortest string is: " + minLengthStr);
}
}
I hope,this will help
public class Test implements Comparator<String>{
public static void main(String[] args) {
// TODO Auto-generated method stub
//String arr[] = {"hei", "hvordan", "gaar", "det", "med", "deg", "a"};
Set<String> set = new TreeSet<String>(new Test());
set.add("hei");
set.add("hvordan");
set.add("gaar");
set.add("med");
set.add("deg");
set.add("a");
System.out.println(set);
}
#Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
if(o1.length()>o2.length())
return 1;
else if(o1.length()<o2.length())
return -1;
else
return 0;
}
If you want to play with String, Comparable and compareTo here is an example.
ideone.com
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Test {
String arr[] = {"hei", "hvordan", "gaar", "det", "med", "deg", "a"};
/**
* Use composition.
*/
class MyComparableString implements Comparable<MyComparableString> {
String myString;
MyComparableString(String s) {
myString = s;
}
#Override
public int compareTo(MyComparableString other) {
// Compare the lengths of the strings in this and other.
Integer l1 = myString.length();
Integer l2 = other.myString.length();
return l1.compareTo(l2);
}
// String representation.
public String toString() {
return myString;
}
}
void go() {
// Convert the String array into a List (Collection) of MyComparableString.
List<MyComparableString> l = new ArrayList<>();
for (String s: arr) {
l.add(new MyComparableString(s));
}
// Print longest and shortest.
System.out.println("Shortest: " + Collections.min(l));
System.out.println("Longest: " + Collections.max(l));
}
public static void main(String[] args) {
new Test().go();
}
}
I have a TreeMap in which I have stored some values. The map is sorted using the values, from highest to lowest. Now I want print out the contents of the TreeMap with their various indices.
If I have the following pairs in the map :
("Andrew", 10),
("John", 5),
("Don",9),
("Rolex", 30),
("Jack", 10),
("Dan",9)
I want to print out:
Rolex, 30 , 1
Jack, 10, 2
Andrew, 10, 2
Dan, 9, 4
Don, 9, 4
John, 5, 6.
This is what I've been trying but it doesn't seem to work well:
/**
*
* #author Andrew
*/
import java.util.*;
public class SortArray {
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>>entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
#Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res!= 0 ? res : 1;
//return e1.getValue().compareTo(e2.getValue());
}
});
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
public void test(){
Map mm = new TreeMap();
mm.put("Andrew", 11);
mm.put("Mbata", 21);
mm.put("Chinedu", 14);
mm.put("Bol", 14);
mm.put("Don", 51);
mm.put("Rolex", 16);
mm.put("Son", 41);
SortedSet newMap = entriesSortedByValues(mm);
Iterator iter = newMap.iterator();
int x = newMap.size();
List names = new ArrayList();
List scores = new ArrayList();
while(iter.hasNext()){
String details = iter.next().toString();
StringTokenizer st = new StringTokenizer(details, "=");
String name = st.nextToken();
names.add(name);
String score = st.nextToken();
scores.add(score);
//System.out.println(name + " Score:" +score + " Position:" + x);
x--;
}
Collections.reverse(names);
Collections.reverse(scores);
int pos = 1;
for(int i = 0; i<names.size();){
try{
int y = i+1;
if(scores.get(i).equals(scores.get(y))){
System.out.print("Name: "+ names.get(i)+"\t");
System.out.print("Score: "+ scores.get(i)+"\t");
System.out.println("Position: "+ String.valueOf(pos));
//pos++;
i++;
continue;
} else{
System.out.print("Name: "+ names.get(i)+"\t");
System.out.print("Score: "+ scores.get(i)+"\t");
System.out.println("Position: "+ String.valueOf(pos++));
}
i++;
} catch(IndexOutOfBoundsException e) {}
}
}
public SortArray(){
test();
}
public static void main(String [] args){
new SortArray();
}
}
First of all, Why are you catching that IndexOutOfBoundsException and doing nothing with it? if you run that you'll get that exception thrown (and I thing you already know it) the problem is in your algorithm inside the last "for" loop. I shouldn't give you the solution, but wth... at least you did some effort to make it run, so this is a more less working version:
import java.util.*;
public class SortArray {
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>>entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
#Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res != 0 ? res : 1;
//return e1.getValue().compareTo(e2.getValue());
}
});
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
public void test(){
Map mm = new TreeMap();
mm.put("Andrew", 11);
mm.put("Mbata", 21);
mm.put("Chinedu", 14);
mm.put("Bol", 14);
mm.put("Don", 51);
mm.put("Rolex", 16);
mm.put("Son", 41);
SortedSet newMap = entriesSortedByValues(mm);
Iterator iter = newMap.iterator();
int x = newMap.size();
List names = new ArrayList();
List scores = new ArrayList();
while(iter.hasNext()){
String details = iter.next().toString();
StringTokenizer st = new StringTokenizer(details, "=");
String name = st.nextToken();
names.add(name);
String score = st.nextToken();
scores.add(score);
//System.out.println(name + " Score:" +score + " Position:" + x);
x--;
}
Collections.reverse(names);
Collections.reverse(scores);
int pos;
int posBis = 0;
String lastScore = "";
for(int i = 0; i<names.size(); i++){
System.out.print("Name: "+ names.get(i)+"\t");
System.out.print("Score: "+ scores.get(i)+"\t");
if(i == 0 || !lastScore.equals(scores.get(i))) {
pos = i + 1;
posBis = pos;
} else {
pos = posBis;
}
System.out.println("Position: "+ String.valueOf(pos));
lastScore = (String)scores.get(i);
}
}
public SortArray(){
test();
}
public static void main(String [] args){
new SortArray();
}
}
Your SortedSet is the wrong way to go about this. You can see in your Comparator that it gets a bit messy when both values have to be looked up by the same key then you've got this messy (and incorrect) return res != 0 ? res : 1 (the 1 should really be e1.getKey().compareTo(e2.getKey()) rather than always returning 1).
A better way to go about this would be to just sort the keys yourself in a List, rather than creating a separate SortedSet. This way you don't have to worry about duplicate sorting values.
You can also abstract out the Comparator stuff a little, to make it more reusable in other code later, if you need it.
import java.util.*;
public class PrintSomething {
public static <T extends Comparable<T>> Comparator<T> reverseComparator(final Comparator<T> oldComparator) {
return new Comparator<T>() {
#Override
public int compare(T o1, T o2) {
return oldComparator.compare(o2, o1);
}
};
}
public static <K,V extends Comparable<V>> Comparator<K> keyedComparator(final Map<K,V> lookup) {
return new Comparator<K>() {
#Override
public int compare(K o1, K o2) {
return lookup.get(o1).compareTo(lookup.get(o2));
}
};
}
public static void main(String[] args) {
Map<String, Integer> mm = new HashMap<>();
mm.put("Andrew", 10);
mm.put("John", 5);
mm.put("Don", 9);
mm.put("Rolex", 30);
mm.put("Jack", 10);
mm.put("Dan", 9);
Comparator<String> comparator = reverseComparator(keyedComparator(mm));
List<String> keys = Arrays.asList(mm.keySet().toArray(new String[mm.size()]));
//Collections.sort(keys); // optional, if you want the names to be alphabetical
Collections.sort(keys, comparator);
int rank = 1, count = 0;
Integer lastVal = null;
for (String key : keys) {
if (mm.get(key).equals(lastVal)) {
count++;
} else {
rank += count;
count = 1;
}
lastVal = mm.get(key);
System.out.println(key + ", " + mm.get(key) + ", " + rank);
}
}
}
In general things like SortedSet make more sense when you need to keep the data itself sorted. When you just need to process something in a sorted manner one time they're usually more trouble than they're worth. (Also: is there any reason why you're using a TreeMap? TreeMaps sort their keys, but not by value, so in this case you're not taking advantage of that sorting. Using a HashMap is more common in that case.)
You do a lot of work with the iterator, calling toString(), then splitting the results. And your Comparator is extra work too. Stay with a Map on both sides - you can use keys() and values() more directly, and let Java do the sorting for you. Most of your above code can be replaced with: (for clarity, I changed your name "mm" to "originalMap")
Map<Integer, String> inverseMap = new TreeMap<Integer, String>();
for (Map.Entry<String, Integer> entry : originalMap.entrySet()) {
inverseMap.put(entry.getValue(), entry.getKey());
}
Now, iterate over inverseMap to print the results. Note that if a count does exist twice in originalMap, only one will be printed, which is what you want. But which one gets printed left as an exercise for the reader :-). You might want to be more specific on that.
EDIT ADDED: If you do want to print out duplicate scores, this is not what you want. The original post I read said to skip if they were the same, but I don't see that after the edits, so I'm not sure if this is what OP wants.
Say I have an array of strings:
String[] array = {
"2183417234 somerandomtexthere",
"1234123656 somemorerandomtexthere",
"1093241066 andevenmore",
"1243981234 you get what i mean",
//etc
};
How would I sort this array using the long (it's a long) at the start of the string, so it'll end up looking like this:
String[] array = {
"1093241066 andevenmore",
"1234123656 somemorerandomtexthere",
"1243981234 you get what i mean",
"2183417234 somerandomtexthere",
//etc
};
I've tried everyting from making it an arraylist and using Collections#sort to creating my own comparator, to using a sorted map / tree map and I just can't figure it out.
Thanks.
Use this function:
static long comparedValue(String s) {
return Long.valueOf(s.substring(0, s.indexOf(' ')));
}
and then define a Comparator in terms of it:
public int compare(String left, String right) {
return comparedValue(left) - comparedValue(right);
}
Using Google Guava:
List<String> unsorted = Arrays.asList(array);
Function<String, Long> longFunction = new Function<String, Long>() {
#Override public Long apply(String input) {
return Long.valueOf(input.split(" ")[0]);
}
};
List<String> sorted = Ordering.natural().onResultOf(longFunction).immutableSortedCopy(unsorted);
Or if you don't wanna use a List (you should always prefer collections to arrays):
Arrays.sort(array, Ordering.natural().onResultOf(longFunction));
The input that you have shown works perfectly fine. But that's because all of them have the same number of digits.
public static void main(String[] args) {
String[] array = { "2183417234 somerandomtexthere",
"1234123656 somemorerandomtexthere", "1093241066 andevenmore",
"1243981234 you get what i mean", "999 little shorter"
// etc
};
List<String> list = Arrays.asList(array);
Collections.sort(list);
System.out.println(list);
}
Problems start to occur, when you use some shorter numbers - as 999 shown above...
output will be:
[1093241066 andevenmore, 1234123656 somemorerandomtexthere, 1243981234 you get what i mean, 2183417234 somerandomtexthere, 999 little shorter]
So, to make it working allways - you need your custom comparator, that will be able to split given Strings, and then take the number part out of them, and compare them. Using #Marko Topolik solution:
static long comparedValue(String s) {
return Long.valueOf(s.substring(0, s.indexOf(' ')));
}
public int compare(String left, String right) {
long result = comparedValue(left) - comparedValue(right);
boolean numberPartAreEqual = result == 0;
if (numberPartAreEqual) {
result = left.compareTo(right);
}
return (int) result;
}
A custom comparator should work fine:
public class LongPrefixComparator implements Comparator<String> {
#Override
public int compare(String s1, String s2) {
final long pref1 = getPrefixValue(s1);
final long pref2 = getPrefixValue(s2);
return s1 == s2 ? 0 : s1 < s2 ? -1 : 1;
}
private static long getPrefixValue(String stg) {
int len = stg.indexOf(' ');
if (len > 0) {
try {
return Long.parseLong(stg.substring(0, len));
catch (NumberFormatException ignored) {}
}
return 0L;
}
}
From the input string provided:
{ "200,400,7,1", "100,0,1,1", "200,200,3,1", "0,400,11,1",
"407,308,5,1","100,600,9,1" } ,
I am adding the same in a TreeSet and want it to be sorted with the 3rd element order, so the expected output will be:
(100,0,1,1) (200,200,3,1) (407,308,5,1) (200,400,7,1) (100,600,9,1) (0,400,11,1)
But my actual output is:
(100,0,1,1)(0,400,11,1)(200,200,3,1)(407,308,5,1)(200,400,7,1)(100,600,9,1)
But since the string comparison of 11 is less than 9 but in terms of integer , 11>9 . My expected output is getting differed. Suggest me some idea to resolve the same.
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetComparator {
public static void main(String[] args) {
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(String a, String b) {
String aStr = a;
String bStr = b;
String[] splitA = aStr.split(",");
String[] splitB = bStr.split(",");
return splitA[2].compareTo(splitB[2]);
}
};
String[] arr = { "200,400,7,1", "100,0,1,1", "200,200,3,1",
"0,400,11,1", "407,308,5,1", "100,600,9,1" };
TreeSet<String> ts = new TreeSet<String>(comparator);
for (String str : arr) {
ts.add(str);
}
for (String element : ts)
System.out.print(element + " ");
}
}
You're sorting in a lexicographical order ("123" comes before "20"), what you need to do is convert them to integers, and then compare them:
Not:
return splitA[2].compareTo(splitB[2]);
but:
return Integer.valueOf(splitA[2]).compareTo(Integer.valueOf(splitB[2]));
However, a somewhat cleaner way would be to create a custom object holding these 4 different values and then create a Comparator that compares the 3rd value of such an object:
The following:
public class Main {
public static void main (String[] args) {
Comparator<CustomObject> sortOn3rdValue = new Comparator<CustomObject>() {
#Override
public int compare(CustomObject o1, CustomObject o2) {
return o1.v3 < o2.v3 ? -1 : o1.v3 > o2.v3 ? 1 : 0;
}
};
Set<CustomObject> objects = new TreeSet<CustomObject>(sortOn3rdValue);
String[] arr = { "200,400,7,1", "100,0,1,1", "200,200,3,1", "0,400,11,1", "407,308,5,1", "100,600,9,1" };
for(String a : arr) {
objects.add(new CustomObject(a.split(",")));
}
for(CustomObject co : objects) {
System.out.println(co);
}
}
}
class CustomObject {
final int v1, v2, v3, v4;
CustomObject(String[] strValues) {
// assume strValues.lenght == 4
v1 = Integer.valueOf(strValues[0]);
v2 = Integer.valueOf(strValues[1]);
v3 = Integer.valueOf(strValues[2]);
v4 = Integer.valueOf(strValues[3]);
}
#Override
public String toString() {
return String.format("(%d,%d,%d,%d)", v1, v2, v3, v4);
}
}
would print:
(100,0,1,1)
(200,200,3,1)
(407,308,5,1)
(200,400,7,1)
(100,600,9,1)
(0,400,11,1)