I have a TreeTable and would like to perform the sort by number and alphabetically when clicking on header.
Example:
On a first click, I have to check that the column content is sorted by number
If I click on another column that contains String data, I have to check that column content is sorted alphabetically.
Are there known functions that could I use?
I've used Collections for sorting number , but how do I can make the sort alphabetically ?
Collections.sor(myList) is OK for sorting by number but I would sort data alphabetically.
thanks
This can easily be done via Collections.sort(...). Create a copy of your list, sort it and check if they are equal.
Example:
List <String> copy = new ArrayList <String>(original);
Collections.sort(copy);
assertEquals(copy, original);
This can be done, if the elements in the list are comparable (i.e. are of type T implements Comparable <T>). Strings are comparable, and their default comparator sorts them alphabetically (though upper-case are always comes before lower-case)
You may also provide a Comparator for a more flexible sorting.
Here is a more complicated example.
List <String> unholyBible = new ArrayList <String>();
unholyBible.add("armageddon");
unholyBible.add("abyss");
unholyBible.add("Abaddon");
unholyBible.add("Antichrist");
Collections.sort(unholyBible);
System.out.println(unholyBible);
This will print us [Abaddon, Antichrist, abyss, armageddon]. This is because default comparation is case-sensitive. Lets fix it:
List <String> unholyBible = new ArrayList <String>();
unholyBible.add("armageddon");
unholyBible.add("abyss");
unholyBible.add("Abaddon");
unholyBible.add("Antichrist");
Collections.sort(unholyBible, new Comparator <String>() {
public int compare(String o1, String o2){
return o1.compareToIgnoreCase(o2);
}
});
System.out.println(unholyBible);
This one prints [Abaddon, abyss, Antichrist, armageddon].
Now you may worship Satan in strict alphabetical order.
See also
Comparator API
Collections.sort(List, Comparator)
Related
As I used Comparator for sorting a library after the author's name, I just coincidentally "found" something, which actually works perfectly, but I don't understand why. Firstly please have a look at my code:
public class Bookshelf{
Collection<Literature> shelf = new ArrayList<Literature>();
ArrayList<Literature> unsorted = (ArrayList<Literature>)shelf;
public void printShelf() {
Comparator<Literature> compareBySurname= new Comparator<Literature>() {
#Override
public int compare(Literature o1, Literature o2) {
return o1.author.surname.compareTo(o2.author.surname);
}
};
unsorted.sort(compareBySurname);
for (Literature c : shelf)
System.out.println(c);
}
}
As you can see, I am sorting the ArrayList "unsorted". But after I sort it, I am iterating through the Collection "shelf" and printing the elements of the Collection "shelf".And the output is a list of sorted elements by surname.
To achive my intention, I actually should iterate through the ArrayList "unsorted" and print the elements (of course this option works too). So my question is, why the first methode actually works too? :D So I am not sorting the Collection "shelf" directly, but I get a sorted list.
Thanks in advance!
ArrayList<Literature> unsorted = (ArrayList<Literature>)shelf; does not create a new ArrayList. It simply makes unsorted refer to the same ArrayList as shelf. They are not different objects. You want something like
ArrayList<Literature> unsorted = new ArrayList<>(shelf); // <-- a different List.
Because both lists share the same memory reference when you assign the list with the "=" operator. To have a new list with another reference, you must use the key name "new".
I want to sort an ArrayList of type String using a comparator. I have only found examples on how to do it if an ArrayList stores objects.
I have an ArrayList of strings that have 10 symbols and last 5 of those symbols are digits that form a number. I want to solve an array list in ascending order of those numbers that are at the end of each string. How can I do that?
Thanks!
This is one way to accomplish your task; sorted accepts a Comparator object.
List<String> result = myArrayList.stream().sorted(Comparator.comparingInt(e -> Integer.parseInt(e.substring(5))))
.collect(Collectors.toList());
or simply:
myArrayList.sort(Comparator.comparingInt(e -> Integer.parseInt(e.substring(5))));
Collections.sort can sort you a list with a Comparator. Plus you need String.substring:
Collections.sort(list, new Comparator<String>(){
#Override
public int compare(String o1, String o2) {
return o1.substring(5).compareTo(o2.substring(5));
}
});
Collections.sort(list, String::compareTo);
The above code does the job.
If you want more control, you could use/chain with one of the static methods available in the Comparator Interface.
Collectios.sort(list, Comparator.comparing(String::CompareTo).thenComparingInt(String::length));
My program has to use the Collections sort method to sort the ArrayList of Strings lexicographically but each String has a corresponding integer value stored in a separate ArrayList. I want to sort them both the same so the integer values stay with the correct Strings. And if you know a better way to store both values I'm all ears.
public class a5p1b {
public static void main(String[] args) {
Scanner input = new Scanner(System.in).useDelimiter("[^a-zA-z]+");
// ArrayLists to store the Strings and the frequencies
ArrayList<String> lst = new ArrayList<String>();
ArrayList<Integer> intLst = new ArrayList<Integer>();
//loops through as long as there is user input
while (input.hasNext()) {
String str = input.next().toLowerCase();
// if the list already has the string it doesn't add it and it
// ups the count by 1
if (lst.contains(str)) {
int index = lst.indexOf(str);
intLst.set(index, intLst.get(index) + 1);
} else {
// if the word hasnt been found yet it adds it to the list
lst.add(str);
intLst.add(1);
}
}
}
}
You are getting your abstractions wrong. If that string and that number belong together, then do not keep them in two distinct lists.
Instead create a class (or maybe use one of the existing Pair classes) that holds those two values. You can then provide an equals method for that class; plus a specific comparator, that only compares the string elements.
Finally, you put objects of that class into a single list; and then you sort that list.
The whole idea of good OO programming is to create helpful abstractions!
For the record: as dnault suggests, if there is really no "tight" coupling between strings and numbers you could also use a TreeMap (to be used as TreeMap<String, Integer>) to take care of sorting strings that have a number with them.
Try
inList.sort(Comparator.comparing(i -> i.toString());
Although, I don't think the two lists is a good idea.
You should use a Map to associate each unique String key with an Integer value.
Then you can invoke Collections.sort on the map's set of keys returned by keySet().
Additionally, if you use a SortedMap such as TreeMap, it is not necessary to sort the keys. However that solution may not fulfill the requirements of your "Assignment 5 Problem 1b."
I want to achieve the following, I have a collection of dates in a list form which I want deduped and sorted. I'm using collections.sort to sort the list in ascending date order and then using a treeSet to copy and dedupe elements from the list. This is a 2 shot approach ? Is there a faster, 1 step approach ?
EDIT::
Metadata
{
String name;
Date sourceDate;
}
Basically I want to order Metadata object based on the sourceDate and dedupe it too.
You can skip the Collections#sort step: TreeSet will remove duplicates and sort the entries. So basically it is a one line operation:
Set<Date> sortedWithoutDupes = new TreeSet<Date> (yourList);
If the Date is a field in your object, you can either:
have your object implement Comparable and compare objects based on their date
or pass a Comparator<YourObject> as an argument to the TreeSet constructor, that sorts your objects by date
In both cases, you don't need to pre-sort your list.
IMPORTANT NOTE:
TreeSet uses compareTo to compare keys. So if 2 keys have the same date but different names, you should make sure that your compare or compareTo method returns a non-0 value, otherwise the 2 objects will be considered equal and only one will be inserted.
EDIT
The code could look like this (not tested + you should handle nulls):
Comparator<Metadata> comparator = new Comparator<Metadata>() {
#Override
public int compare(Metadata o1, Metadata o2) {
if (o1.sourceDate.equals(o2.sourceDate)) {
return o1.name.compareTo(o2.name);
} else {
return o1.sourceDate.compareTo(o2.sourceDate);
}
}
};
Set<Metadata> sortedWithoutDupes = new TreeSet<Metadata> (comparator);
sortedWithoutDupes.addAll(yourList);
TreeSet will automatically sort its elements, so you shouldn't need to sort the list before adding to the set.
I have a scenario where I have two ArrayLists
ArrayList<String> sortedArrayList
ArrayList<String> unSortedArrayList
I have to sort unSortedArrayList depending on the sortedArrayList.
i.e, sortedArrayList is already sorted, now based on sortedArrayList, I have to sort unSortedArrayList.
unSortedArrayList size is <= to the size of sortedArrayList.
Is there a Java API for that?
Any help is appreciated.
Using Google Guava's excellent Ordering class:
Collections.sort(unSortedArrayList, Ordering.explicit(sortedArrayList));
EDIT You can also do
List<whatever> sortedList = Ordering.explicit(sortedArrayList).immutableSortedCopy(unsortedArrayList);
As I understand what you have is that each element in list 1 has a corresponding element in list 2, and you want list 2 sorted into the order of the 'corresponding' elements. Your best approach is to create an object to contain both Strings:
class StringPair {
String s1;
String s2;
}
Now make an array list of StringPairs and sort it based on the value of s1.
List<String> newSortedList = new ArrayList<String>();
for(String currentSortedStr:sortedList){
if(unsortedList.size==0)break;
if(unsortedList.remove(currentSortedStr)){
newSortedList.add(currentSortedStr);
}
}
You can do something like this if you mean what #Sam Dufel says in the comment
As far as I know there is not such API method for this case.
This is not gonna take care of duplicates. remove will remove only the first occurence of that object. At the if the unsorted list size is greater than 0, you can say it contains duplicates. And if you need duplicates as well, you may wanna add some code to handle that case as well.
or if you mean the normal sorting;
Collections.sort(List<T>) will do the sorting for you.
Another way of doing it;
Collections.sort(unsortedList,new CustomComparator(sortedList));
public class CustomComparator implements Comparator<String>{
private List<String> sortedList;
public CustomComparator(List<String> sortedList){
this.sortedList = sortedList;
}
#Override
public int compare(String o1, String o2) {
return sortedList.indexOf(o1)-sortedList.indexOf(o2);
}
}
Although your question is not clear enough I think that the following will help you.
You can use Collections.sort() to sort list. If you need some custom modification to sort mechanism implement your own Comparator and use 2 args version of this method: Collections.sort(list, comparable)