I have an arraylist defined whose elements are say, [man, animal, bird, reptile]. The elements in the arraylist are non-mandatory. The list can even be empty.
I always need to give the output as [animal,man,reptile,bird]. Means, the order of the elements are to be maintained. Is there any way of doing in arraylist?
I thought I can do like
for (String listElement: customList) { //custom list variable holds all elements
if (listElement.equalsIgnoreCase("animal"){
newList.add(0, listElement);
} else if("man") {
newlist.add(1, listElement);
}
But I would want to know the best practice of doing. Can someone please help me on this?
You can define a custom sorting and use it to order your array (save the comparator somewhere, so you don't have to instantiate it many times):
List<String> definedOrder = // define your custom order
Arrays.asList("animal", "man", "reptile", "bird");
Comparator<String> comparator = new Comparator<String>(){
#Override
public int compare(final String o1, final String o2){
// let your comparator look up your car's color in the custom order
return Integer.valueOf(definedOrder.indexOf(o1))
.compareTo(Integer.valueOf(definedOrder.indexOf(o2)));
}
};
Collections.sort(myList, comparator);
Use a custom comparator:
Collections.sort(customList, comparator);
int i = 0;
for (String temp : customList) {
System.out.println("customList " + ++i + " : " + temp);
}
Custom comparator below:
public static Comparator<String> comparator = new Comparator<String>() {
public int compare(String str1, String str2) {
return orderOf(str1) - orderOf(str2);
}
private int orderOf(String name) {
return ((List)Arrays.asList("animal", "man", "reptile", "bird")).indexOf(name);
}
};
You can use Collections.sort(yourArrayList, new CustomComparator());
You need to create your own comparator for this, though, but it is easy.
public class CustomComparator implements Comparator<YourType>{
#Override
public int compare(YoyrType o1, YoyrType o2) {
// logic for ordering the list
}
}
arraylist is ordered.
maybe you want to insert element into the list.
could you create a new list every time when you have to insert and copy each of them?
Related
I have an arraylist with values ... ST1000, ST 5000, ST 30000, ST400, ST500, SP1000, SP600
I want it o be sorted like ST1000, ST2000, ST3000, ST4000, SP600, SP1000 .. How can I do that?
Thanks
you can use the compareTo which will compare it for you lexicographically
here are 2 methods to sort your list using java 8
list.stream()
.sorted((s1, s2) -> s1.compareTo(s2)).collect(Collectors.toList());
list.sort((s1, s2)->s1.compareTo(s2));
using java 8, you don't have to use Collections.sort method
You can sort any collection in a desired manner with a Collections.sort(List<T> list, Comparator<? super T> c) method.
All you need to do is to realize Comparator's compare method accordingly.
In your particular case it would go something like this:
List<String> list = Arrays.asList("ST1000", "ST5000", "ST30000", "ST400", "ST500", "SP1000", "SP600");
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
String o1Prefix = o1.substring(0, 2);
String o2Prefix = o2.substring(0, 2);
if (o1Prefix.equals(o2Prefix)) {
return Integer.parseInt(o1.substring(2, o1.length())) > Integer.parseInt(o2.substring(2, o2.length())) ? 1 : -1;
} else if (o1Prefix.equals("ST")) {
return -1;
} else {
return 1;
}
}
});
YOu can create a custom Comparator object and override compare method with the desired logic.
Comparator<Model> customComparator = new Comparator<Model>() {
public int compare(Model arg0, Model arg1) {
//TODO custom sort logic
}
};
if compare returns -1 then the arg0 is less than arg1 , 0 equals and 1 greater
then sort the list using the custom comparator
Collections.sort(list, customComparator);
I am currently trying to order an ArrayList of String elements (called myarraylist) according to the numbers found after the word "Item". Here is a snippet of what is in myarraylist:
Item 1
Item 2
Item 3
...
Item 9
Item 10
I would like to order myarraylist to the following order:
Item 10
Item 9
Item 8
...
Item 3
Item 2
Item 1
So far, this is what I have tried:
Collections.sort(myarraylist, String.CASE_INSENSITIVE_ORDER);
Collections.reverse(myarraylist);
However, this orders the myarraylist in the following order
Item 9
Item 8
...
Item 3
Item 2
Item 10
Item 1
As you can see, Item 10 is out of place, because it reads "10" by its first number, "1". Does anyone know how to appropriately order myarraylist in reverse numerical order?
That's because the default String Comparator uses lexicographical order -- i.e. character by character, as in a dictionary. Since "1" comes before "2", any String starting with "1" will precede any other starting with "2".
You should use a custom comparator to implement Natural Sorting. A good example would be Alphanum, from Dave Koelle, which you would use like this:
Collections.sort(myarraylist, new AlphanumComparator());
I use this simple class to order my Strings:
public abstract class StringOrderer {
public static ArrayList<String> order(ArrayList<String> items, boolean ascending) {
Collections.sort(items, new StringComparator());
// reverse the order
if(!ascending) Collections.reverse(items);
return items;
}
class StringComparator implements Comparator<String> {
#Override
public int compare(String s1, String s2) {
// use the users default locale to sort the strings
Collator c = Collator.getInstance(Locale.getDefault());
return c.compare(s1, s2);
}
}
}
The basic idea is that i have a custom Comparator that uses the default Locale.
Since you are using String in the Array list it alway checks characters. Better you try using Integer. It may works for you.
As String can not be extended, it is better to change ArrayList<String> to ArrayList<ClassWithStringAttribute> then implement Comparable in ClassWithStringAttribute when you need custom comparison. For your particular case and illustration, the following class should work, though not a nice approach.
myarraylist= StringSorter.getSortedList(myarraylist);
Will give you a sorted list
public class StringSorter implements Comparable<StringSorter>{
String tempString;
public StringSorter(String data) {
this.tempString = data;
}
public static List<String> getSortedList(List<String> unsortedList){
List<StringSorter> tempList=new ArrayList<StringSorter>();
for (String current : unsortedList) {
tempList.add(new StringSorter(current));
}
Collections.sort(tempList);
List<String> sortedString=new ArrayList<String>();
for (StringSorter current : tempList) {
sortedString.add(current.tempString);
}
return sortedString;
}
#Override
public int compareTo(StringSorter other) {
Integer otherInt=Integer.parseInt(other.tempString.replaceFirst("Item ", ""));
Integer thisInt=Integer.parseInt(this.tempString.replaceFirst("Item ", ""));
if(otherInt>thisInt){
return -1;
}else if(otherInt<thisInt){
return 1;
}else{
return 0;
}
}
}
How about this custom Comparator,
public class StringNumSuffixComparator implements Comparator<String>{
#Override
public int compare(String o1, String o2) {
String str1 = o1;
String str2 = o2;
Integer num1 = Integer.parseInt(str1.replaceAll("\\D+",""));
Integer num2 = Integer.parseInt(str2.replaceAll("\\D+",""));
return num2.compareTo(num1);
}
}
To sort them with Collections.sort(),
Collections.sort(items, new StringNumSuffixComparator());
I have values in linked list as
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
Pranish,pranishfilan,viper,1234
zxs,asdf,asfd,1234
uv,vr,va,1234
www,dsf,ASDF,123
dsfgsdf,sd,sd,235
The values are seperated by commas which contains certain data. The first ones i.e TY12354d, TY12345saf, Pranish etc are the id, second i.e sfasdf, asdffasd, pranishfilan, etc are name.The values are viewed in jtextfield. I want to enable user to sort the datas according to the id when he clicks on "sort by id" button, name when he clicks on "sort by name" button and so on.
Try this one to sort by id.
LinkedList<String> list = new LinkedList<String>();
list.add("TY12354d,sfasdf,asfasf,2.35123412E8");
list.add("TY12354dsaf,asdffasd,asfasfafsd,12344.0");
list.add("Pranish,pranishfilan,viper,1234");
list.add("zxs,asdf,asfd,1234");
list.add("uv,vr,va,1234");
list.add("www,dsf,ASDF,123");
list.add("dsfgsdf,sd,sd,235");
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) {
System.out.println(a+" --> "+b);
return a.substring(0, a.indexOf(',')).compareTo(b.substring(0, b.indexOf(',')));
}
});
Use same concept for name also.
output:
Pranish,pranishfilan,viper,1234
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
dsfgsdf,sd,sd,235
uv,vr,va,1234
www,dsf,ASDF,123
zxs,asdf,asfd,1234
--EDIT--
as per OP last comment to compare on Car object
class Car {
String id;
String name;
public Car(String id, String name) {
this.id = id;
this.name = name;
}
// getter & setter
}
LinkedList<Car> list = new LinkedList<Car>();
list.add(new Car("TY12354d", "sfasdf"));
list.add(new Car("TY12354dsaf", "asdffasd"));
list.add(new Car("Pranish", "pranishfilan"));
list.add(new Car("zxs", "asdf"));
list.add(new Car("uv", "vr"));
list.add(new Car("www", "dsf"));
list.add(new Car("dsfgsdf", "sd"));
Collections.sort(list, new Comparator<Car>() {
public int compare(Car c1, Car c2) {
return c1.id.compareTo(c2.id);
}
});
You'll have to write your own comparator, or rewrite the structure. With a comparator you can simply use Collections.sort to sort the list.
There are many threads on implementing comparators here on stackoverflow, like this one. It's actually fairly simple.
It's not very efficient to sort a linked list, so if you don't use Collections.sort, which uses an intermediate array to sort, I'd suggest that you change your datastructure to e.g. an array or ArrayList. Or, even better: create a Class to represent your data and define comparators for that class.
Here's an example of a Comparator:
import java.util.*;
class Test {
static class IDComparator implements Comparator<String> {
#Override
public int compare(String a, String b) {
return a.split(",")[0].compareToIgnoreCase(b.split(",")[0]);
}
}
public static void main(String[] args) {
LinkedList<String> ll = new LinkedList<String>();
ll.add("TY12354d,sfasdf,asfasf,2.35123412E8");
ll.add("TY12354dsaf,asdffasd,asfasfafsd,12344.0");
ll.add("Pranish,pranishfilan,viper,1234");
System.out.println("Before sorting on ID:\n");
for (String s : ll) {
System.out.println(s);
}
Collections.sort(ll,new IDComparator());
System.out.println("\nAfter sorting on ID:\n");
for (String s : ll) {
System.out.println(s);
}
}
}
Output:
Before sorting on ID:
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
Pranish,pranishfilan,viper,1234
After sorting on ID:
Pranish,pranishfilan,viper,1234
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
This is not the prettiest code I've written. I especially don't like the comparator itself, with a hard coded index. However, it'll give you an idea of how to proceed with custom comparators.
I got an object Recipe that implements Comparable<Recipe> :
public int compareTo(Recipe otherRecipe) {
return this.inputRecipeName.compareTo(otherRecipe.inputRecipeName);
}
I've done that so I'm able to sort the List alphabetically in the following method:
public static Collection<Recipe> getRecipes(){
List<Recipe> recipes = new ArrayList<Recipe>(RECIPE_MAP.values());
Collections.sort(recipes);
return recipes;
}
But now, in a different method, lets call it getRecipesSort(), I want to sort the same list but numerically, comparing a variable that contains their ID. To make things worse, the ID field is of the type String.
How do I use Collections.sort() to perform the sorts in Java?
Use this method Collections.sort(List,Comparator) . Implement a Comparator and pass it to Collections.sort().
class RecipeCompare implements Comparator<Recipe> {
#Override
public int compare(Recipe o1, Recipe o2) {
// write comparison logic here like below , it's just a sample
return o1.getID().compareTo(o2.getID());
}
}
Then use the Comparator as
Collections.sort(recipes,new RecipeCompare());
The answer given by NINCOMPOOP can be made simpler using Lambda Expressions:
Collections.sort(recipes, (Recipe r1, Recipe r2) ->
r1.getID().compareTo(r2.getID()));
Also introduced after Java 8 is the comparator construction methods in the Comparator interface. Using these, one can further reduce this to 1:
recipes.sort(comparingInt(Recipe::getId));
1 Bloch, J. Effective Java (3rd Edition). 2018. Item 42, p. 194.
Create a comparator which accepts the compare mode in its constructor and pass different modes for different scenarios based on your requirement
public class RecipeComparator implements Comparator<Recipe> {
public static final int COMPARE_BY_ID = 0;
public static final int COMPARE_BY_NAME = 1;
private int compare_mode = COMPARE_BY_NAME;
public RecipeComparator() {
}
public RecipeComparator(int compare_mode) {
this.compare_mode = compare_mode;
}
#Override
public int compare(Recipe o1, Recipe o2) {
switch (compare_mode) {
case COMPARE_BY_ID:
return o1.getId().compareTo(o2.getId());
default:
return o1.getInputRecipeName().compareTo(o2.getInputRecipeName());
}
}
}
Actually for numbers you need to handle them separately check below
public static void main(String[] args) {
String string1 = "1";
String string2 = "2";
String string11 = "11";
System.out.println(string1.compareTo(string2));
System.out.println(string2.compareTo(string11));// expected -1 returns 1
// to compare numbers you actually need to do something like this
int number2 = Integer.valueOf(string1);
int number11 = Integer.valueOf(string11);
int compareTo = number2 > number11 ? 1 : (number2 < number11 ? -1 : 0) ;
System.out.println(compareTo);// prints -1
}
Use the method that accepts a Comparator when you want to sort in something other than natural order.
Collections.sort(List, Comparator)
Sort the unsorted hashmap in ascending order.
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2)
{
return o2.getValue().compareTo(o1.getValue());
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
ok I was going to edit my previous question but i wasnt sure if it was the right way to do it so i'll just give another question about Comparator, now i want to be able to sort with different ways. I have a bank checks and i want to sort with checkNumber then checkAmount
i managed to do it with checkNumber but couldnt figure out how with checkAmount
here is how i did it for checkNumber:
import java.util.Comparator;
public class Check implements Comparator {
private int checkNumber;
private String description;
private double checkAmount;
public Check() {
}
public Check(int newCheckNumber, double newAmountNumber) {
setCheckNumber(newCheckNumber);
setAmountNumber(newAmountNumber);
}
public String toString() {
return checkNumber + "\t\t" + checkAmount;
}
public void setCheckNumber(int checkNumber) {
this.checkNumber = checkNumber;
}
public int getCheckNumber() {
return checkNumber;
}
public void setAmountNumber(double amountNumber) {
this.checkAmount = amountNumber;
}
public double getAmountNumber() {
return checkAmount;
}
#Override
public int compare(Object obj1, Object obj2) {
int value1 = ((Check) obj1).getCheckNumber();
int value2 = ((Check) obj2).getCheckNumber();
int result = 0;
if (value1 > value2){
result = 1;
}
else if(value1 < value2){
result = -1;
}
return result;
}
}
import java.util.ArrayList;
import java.util.Collections;
import test.CheckValue;
public class TestCheck {
public static void main(String[] args) {
ArrayList List = new ArrayList();
List.add(new Check(445, 55.0));
List.add(new Check(101,43.12));
List.add(new Check(110,101.0));
List.add(new Check(553,300.21));
List.add(new Check(123,32.1));
Collections.sort(List, new Check());
System.out.println("Check Number - Check Amount");
for (int i = 0; i < List.size(); i++){
System.out.println(List.get(i));
}
}
}
thank you very much in advance and please tell me if im submiting things in the wrong way.
What you really want to do is define a separate class to act as the Comparator object - don't make your actual Check class the comparator, but instead have 3 classes:
the Check class itself
a CheckAmountComparator class (or something similar) that implements Comparator<Check>
a CheckNumberComparator class (or something similar) that implements Comparator<Check>
Then when you want to sort one way or another, you simply pass an instance of the Comparator-implementing class corresponding to the type of sorting you want to do. For instance, to sort by amount, it'd then become...
Collections.sort(yourListVariable, new CheckAmountComparator());
Also - I'd highly suggest naming your variable something other than List, since List is used as a type name in Java.
You should make Check implements Comparable<Check>, but not itself implements Comparator.
A Comparable type defines the natural ordering for the type, and a Comparator for a type is usually not the type itself, and defines their own custom ordering of that type.
Related questions
When to use Comparable vs Comparator
Java: What is the difference between implementing Comparable and Comparator?
Can I use a Comparator without implementing Comparable?
Also, you shouldn't use raw type. You need to use parameterized generic types, Comparable<Check>, Comparator<Check>, List<Check>, etc.
Related questions
What is a raw type and why shouldn’t we use it?
A String example
Let's take a look at what String has:
public final class String implements Comparable<String>
String defines its natural ordering as case-sensitive
It has a field
public static final Comparator<String> CASE_INSENSITIVE_ORDER
Here we have a case-insensitive custom Comparator<String>
An example of using this is the following:
List<String> list = new ArrayList<String>(
Arrays.asList("A", "B", "C", "aa", "bb", "cc")
);
Collections.sort(list);
System.out.println(list);
// prints "[A, B, C, aa, bb, cc]"
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
System.out.println(list);
// prints "[A, aa, B, bb, C, cc]"
Here's an example of sorting List<String> using both its natural ordering and your own custom Comparator<String>. Note that we've defined our own Comparator<String> without even changing the final class String itself.
List<String> list = new ArrayList<String>(
Arrays.asList("1", "000000", "22", "100")
);
Collections.sort(list);
System.out.println(list);
// prints "[000000, 1, 100, 22]" natural lexicographical ordering
Comparator<String> lengthComparator = new Comparator<String>() {
#Override public int compare(String s1, String s2) {
return Integer.valueOf(s1.length())
.compareTo(s2.length());
}
};
Collections.sort(list, lengthComparator);
System.out.println(list);
// prints "[1, 22, 100, 000000]" ordered by length
Comparator<String> integerParseComparator = new Comparator<String>() {
#Override public int compare(String s1, String s2) {
return Integer.valueOf(Integer.parseInt(s1))
.compareTo(Integer.parseInt(s2));
}
};
Collections.sort(list, integerParseComparator);
System.out.println(list);
// prints "[000000, 1, 22, 100]" ordered by their values as integers
Conclusion
You can follow the example set by String, and do something like this:
public class Check implements Comparable<Check> {
public static final Comparator<Check> NUMBER_ORDER = ...
public static final Comparator<Check> AMOUNT_ORDER = ...
public static final Comparator<Check> SOMETHING_ELSE_ORDER = ...
}
Then you can sort a List<Check> as follows:
List<Check> checks = ...;
Collections.sort(checks, Check.AMOUNT_ORDER);