Reputation: 119
I want to sort a list of String that also contains numbers.
For example, I have a list containing elements "1,2,3,4,5,11,12,21,22,31,32,A101,A102,A103,A104,B405"
.
If i use Collection.sort method means output is "1,11,12,2,21,22,3,31,32... "
.
If i use Comparator function means it gives
output as "1,2,3,4,5,11,12,21,22,31,32,A101... ".
But i need to display as
"A101,A102,A103,A104,B405,1,2,3,4,5,11,12,21,22,31,32"
Please any one give me a solution. Thanks in advance.
Upvotes: 1
Views: 1381
Reputation: 425
Answer is present there in your question, just create two lists and sort them separately!
package com.kvvssut.misc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SortStringThenNumber {
public static void main(String[] args) {
List<String> inputs = Arrays.asList(new String[]{"1","5","3","4","2","11","11","21","31","32","22","A101","A103","A104","B405","A102"});
List<Object> result = sortStringThenNumber(inputs);
for (Object sorted : result) {
System.out.println(String.valueOf(sorted));
}
}
private static List<Object> sortStringThenNumber(List<String> inputs) {
List<Integer> numbers = new ArrayList<Integer>();
List<String> strings = new ArrayList<String>();
for (String input : inputs) {
if (input.matches("-?\\d+")) {
numbers.add(Integer.valueOf(input));
} else {
strings.add(input);
}
}
inputs = null;
Collections.sort(numbers);
Collections.sort(strings);
ArrayList<Object> all = new ArrayList<Object>();
all.addAll(strings);
all.addAll(numbers);
return all;
}
}
Upvotes: 0
Reputation: 16641
Implement your own comparator that tries to convert the objects to be compared to an integer, and if succesful, uses the compareTo of the Integer class, and otherwise uses the compareTo of the String class.
Like this:
public class MyComparator implements Comparator<String,String>
{
public int compare(String s1, String s2)
{
try
{
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
return i1 - i2;
}
catch (NumberFormatException e)
{
return s1.compareTo(s2);
}
}
}
ArrayList<String> myList = (...);
Collections.sort(myList,new MyComparator());
As commented, this sorts like this 1,12,A102,A103
. But wanted is: A102,A103,1,12
. To do this we need to take care of situations where s1
is parsable as int and s2
is not and the other way around. I'm not sure if I got -1
and 1
right, so maybe they should be swapped.
public class MyComparator implements Comparator<String,String>
{
public int compare(String s1, String s2)
{
Integer i1 = null
Integer i2 = null
try
{
i1 = Integer.parseInt(s1);
}
catch (NumberFormatException e) {}
try
{
i2 = Integer.parseInt(s2);
}
catch (NumberFormatException e) {}
if (i1 == null && i2 == null)
return s1.compareTo(s2);
if (i1 == null && i2 != null)
return -1;
if (i1 != null && i2 == null)
return 1;
return i1 - i2;
}
}
Upvotes: 2
Reputation: 394
Create a new "holder" object for the strings and implement the Comparable interface. Override the "compareTo" method. That should do the trick ;)
Upvotes: 0