Sort List of List [duplicate] - java

This question already has answers here:
Java: How to sort List of Lists by their size?
(3 answers)
Closed 9 months ago.
I have List of Lists(list rows contain list column). I want to sort my rows in ListRZS by length(.size()).
[[123, 189, 277], [11], [145, 211, 299], [156, 222, 310], [167, 233, 255], [189, 266], [200, 277], [211, 288], [245, 299], [233], [244]]
Shoul be:
[[11], [233], [244], [189, 266],[200, 277], [211, 288], [245, 299], [123, 189, 277], [145, 211, 299], [156, 222, 310], [167, 233, 255]]
Question: How to write working comporator/comparable for this situation.
public class Start {
public static void main(String[] args) {
System.out.println("Start reading from Xls");
ReaderXls1Column read = new ReaderXls1Column();
ReaderXls readrzs = new ReaderXls();
List<String> listASU = new ArrayList<String>(read.ReaderXls1Column("Text1obj",0,1)); // Creating Lists
List<List<String>> listRZS = new ArrayList<List<String>>(readrzs.ReadXls("Text1obj",2,12));
System.out.println(listASU);
System.out.println(listRZS);
System.out.println("Reading is over");
System.out.println(listRZS);
WriterXls.main("Text1obj",listRZS);
System.out.println("Writing is over");
}
My attempt without comparator, comparable(of course, not working right)
int k=0;
while ( k<listRZS.size()){
for (int j=0;j<10;j++) {
List<String> tmplist = new ArrayList<String>();
if (listRZS.get(k).size()>listRZS.get(k+1).size()) {Collections.copy(listRZS.get(k),tmplist); listRZS.remove(k); listRZS.add(k+1,tmplist);}
else {};
}
Collections.sort(listRZS.get(k)); // sort each row, solution above
k++;
}

A comparator just needs to implement one method (compare), that takes two items, and returns:
0 if they are equal
positive value if the second is less than the first
negative value if the second is greater than the first.
When sorting integer values, a typical pattern to accomplish this is to reduce each object received in the compare method to an integer, then, if we call them a and b, simply return a - b.
Example (see it running at ideone.com/rcmDbi):
import java.util.*;
class Test {
public static void main(String[] args) {
List<Integer> a = Arrays.asList(1);
List<Integer> b = Arrays.asList(1,2);
List<Integer> c = Arrays.asList(1,2,3);
List<Integer> d = Arrays.asList(1,2,3,4);
List<List<Integer>> test = Arrays.asList(d,b,c,a);
Collections.sort(test, ListSizeComparator.INSTANCE);
for (List<Integer> list : test) {
System.out.println(list.size());
}
}
enum ListSizeComparator implements Comparator<List> {
INSTANCE;
public int compare(List one, List other) {
return one.size() - other.size();
}
}
}
(By the way, I've used an enum for the enum singleton pattern because our Comparator stores no state.)

Try like this:
List<List<String>> myList; // load myList with values
Then do the sorting as follows:
Collections.sort(myList, new Comparator<List<String>>(){
#Override
public int compare(List<String> arg0, List<String> arg1) {
return arg1.size() - arg0.size();
}
});

Related

Representing multisets as LinkedLists

A multiset is similar to a set except that the duplications count.
We want to represent multisets as linked lists. The first representation
that comes to mind uses a LinkedList<T> where the same item can occur at
several indices.
For example:the multiset
{ "Ali Baba" , "Papa Bill", "Marcus", "Ali Baba", "Marcus", "Ali Baba" }
can be represented as a linked list
of strings with "Ali Baba" at index 0, "Papa Bill" at index 1,
"Marcus" at index 2, "Ali Baba" at index 3, and so on, for a total of
6 strings.
The professor wants a representation of the multiset as pair <item,integer> where the integer, called the multiplication of item, tells us how many times item occurs in the multiset. This way the above multiset is represented as the linked list with Pair("Ali Baba" ,3) at index 0, Pair("Papa Bill", 1) at index 1, and Pair("Marcus",2) at index 2.
The method is (he wrote good luck, how nice of him >:[ )
public static <T> LinkedList<Pair<T,Integer>> convert(LinkedList<T> in){
//good luck
}
the method transforms the first representation into the Pair representation.
If in is null, convert returns null. Also feel free to modify the input list.
He gave us the Pair class-
public class Pair<T,S>
{
// the fields
private T first;
private S second;
// the constructor
public Pair(T f, S s)
{
first = f;
second = s;
}
// the get methods
public T getFirst()
{
return first;
}
public S getSecond()
{
return second;
}
// the set methods
// set first to v
public void setFirst(T v)
{
first = v;
}
// set second to v
public void setSecond(S v)
{
second = v;
}
}
I am new to programming and I've been doing well, however I have no idea how to even start this program. Never done something like this before.
If you are allowed to use a temporary LinkedList you could do something like that:
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<String> test = new LinkedList<String>();
test.add("Ali Baba");
test.add("Papa Bill");
test.add("Marcus");
test.add("Ali Baba");
test.add("Marcus");
test.add("Ali Baba");
LinkedList<Pair<String, Integer>> result = convert(test);
for(Pair<String, Integer> res : result) {
System.out.println(res.getFirst() + " :" + res.getSecond());
}
}
public static <T> LinkedList<Pair<T, Integer>> convert(LinkedList<T> in) {
LinkedList<Pair<T, Integer>> returnList = new LinkedList<>();
LinkedList<T> tmp = new LinkedList<T>();
// iterate over your list to count the items
for(T item : in) {
// if you already counted the current item, skip it
if(tmp.contains(item)) {
continue;
}
// counter for the current item
int counter = 0;
//iterate again over your list to actually count the item
for(T item2 : in) {
if(item.equals(item2)) {
counter ++;
}
}
// create your pair for your result list and add it
returnList.add(new Pair<T, Integer>(item, counter));
// mark your item as already counted
tmp.add(item);
}
return returnList;
}
}
With that i get the desired output of
Ali Baba :3
Papa Bill :1
Marcus :2
Your requirements put:
your input : LinkedList
your output : LinkedList>
1 - write a loop to read your input
2 - process / store it in a convenient way: user Map . In fact, use linkedhashmap which keeps the order
2bis - if you can't use a Map, do the same thing directly with two arrays: an array of T, and an array of integer. You must manager insertion, search, and keep count.
3 - iterate over your arrays, and create your output
It is easier to begin with 2, and if it works, replace with 2bis

Java: How to sort two corresponding arrays?

I have two arrays:
First array:
25, 20, 50, 30, 12, 11...
Second Array:
New York, New Jersey, Detroit, Atlanta, Chicago, Los Angeles
Every two cities from the second array correspond to one value from the first.
Example: New York and New Jersey would correspond to 25, Detroit and Atlanta would correspond to 20 and so on.
I want to reorder the first Array's numbers in descending order (50, 30, 25, 20...), but I also want the cities of the second array to be shifted accordingly so that they have the same value before and after the sort.
How do I accomplish this task? (I can use either an ArrayList or an Array, whichever works out simpler)
You can use TreeMap:
Map<Integer, String[]> map = new TreeMap<>();
for(int i=0;i<firstArray.length;i++){
map.put(firstArray[i], new String[]{secondArray[i * 2], secondArray[i*2+1]});
}
And this map will be sorted by key natural order.
But I would suggest you to make container class. Something like:
public class CityPair{
public int value;
public String[] cities = new String[2];
}
Now you can fill the list by your data:
...
ArrayList list = new ArrayList<CityPair>();
for(int i=0; i<firstArray.length; i++){
CityPair pair = new CityPair();
pair.value = firstArray[i];
pair.cities[0] = secondArray[i*2];
pair.cities[1] = secondArray[i*2+1];
list.add(pair);
}
...
As you see, I didn't check indexes for "index out of bounds", but you should. After that you can sort your list. You could do it manually using for example Bubble sort algorithm, but better way is write custom comparator:
public class CityPairComparator implements Comparator<CityPair> {
#Override
public int compare(CityPair pair1, CityPair pair2) {
return Integer.compare(pair1.value, pair2.value);
}
}
Now you can sort your list with Collections utility class:
Collections.sort(list, new CityPairComparator());
With this approch you can replace String[] cities in CityPair class for ArrayList<Sting> cities. Then it's will be able to add more than two cities per value.
Here's a (4 line) solution that also handles mismatched array lengths:
int[] numbers = {25, 20, 50};
String[] cities = {"New York", "New Jersey", "Detroit", "Atlanta", "Chicago", "Los Angeles"};
Map<Object, Object> map = new TreeMap<>(Comparator.comparing(Integer.class::cast, Integer::compare).reversed());
for (Iterator<?> n = Arrays.stream(numbers).iterator(),
s = Arrays.stream(String.join(",", cities).split(",(?=(([^,]*,){2})*[^,]*,[^,]*$)")).iterator();
n.hasNext() && s.hasNext(); )
map.put(n.next(), s.next());
numbers = map.keySet().stream().map(String::valueOf).mapToInt(Integer::parseInt).toArray();
cities = map.values().stream().map(String::valueOf).map(s -> s.split(",")).flatMap(Arrays::stream).toArray(String[]::new);
This creates two iterators on the fly from streams of each array, both typed to Object to allow dual initialization within the for loop. The cities array is first joined into one string then split into pairs-as-a-String (using an appropriate regex). The elements of both iterators populate a TreeMap, which has a reversed Integer comparator.
Because TreeMaps iterate in sorted order, a stream of keySet() and values() can be used to generate the resulting arrays.
The for loop's terminal condition checks both iterators to see if there's a next element available, which causes excess elements of the longer array to be ignored if the arrays aren't of equal length.
I have tried a solution like this, It is using Arraylist as per your requirement :
First I have created a new data structure for your operation. As each value will hold two city name:
public class Citizen implements Comparable<Citizen> {
private int citizenId;
private String subjectOne;
private String subjectTwo;
public Citizen(int rollNumber, String subjectOne, String subjectTwo){
this.citizenId = rollNumber;
this.subjectOne = subjectOne;
this.subjectTwo = subjectTwo;
}
public int getRollNumber() {
return citizenId;
}
public void setRollNumber(int rollNumber) {
this.citizenId = rollNumber;
}
public String getSubjectOne() {
return subjectOne;
}
public void setSubjectOne(String subjectOne) {
this.subjectOne = subjectOne;
}
public String getSubjectTwo() {
return subjectTwo;
}
public void setSubjectTwo(String subjectTwo) {
this.subjectTwo = subjectTwo;
}
public int compareTo(Citizen comparestu) {
int compareage=((Citizen)comparestu).getRollNumber();
/* For Ascending order*/
return this.citizenId-compareage;
/* For Descending order do like this */
//return compareage-this.studentage;
}
#Override
public String toString() {
return "[ rollno=" + citizenId + ", subjectOne=" + subjectOne + ", subjectTwo=" + subjectTwo + "]";
}
}
As you can see here the parameter for comparison is taken as citizenID using implementation of Comparable interface.
now to call :
public static void main(String[] args) {
ArrayList<Citizen> studentList = new ArrayList<Citizen>();
studentList.add(new Citizen(25, "New York", "New Jersey"));
studentList.add(new Citizen(20, "Detroit", "Atlanta"));
studentList.add(new Citizen(50, "Chicago", "Los Angeles"));
studentList.add(new Citizen(30, "Kolkata", "Delhi"));
studentList.add(new Citizen(12, "Munmbai", "Baranasi"));
studentList.add(new Citizen(11, "Bangalore", "Goa"));
Collections.sort(studentList);
for(Citizen student: studentList){
System.out.println(student);
}
}
output :
[ rollno=11, subjectOne=Bangalore, subjectTwo=Goa]
[ rollno=12, subjectOne=Munmbai, subjectTwo=Baranasi]
[ rollno=20, subjectOne=Detroit, subjectTwo=Atlanta]
[ rollno=25, subjectOne=New York, subjectTwo=New Jersey]
[ rollno=30, subjectOne=Kolkata, subjectTwo=Delhi]
[ rollno=50, subjectOne=Chicago, subjectTwo=Los Angeles]
Java 8 provides a slightly more elegant way to do this without needing a separate map:
int[] array1;
String[] array2;
array2 = IntStream.range(0, Math.min(array1, array2))
.boxed().sorted(Comparator.comparingInt(i -> array1[i]))
.map(i -> array2[i])
.toArray(array2);
The boxing is only required because IntStream does not have a sorted method with a custom Comparator. I'm not sure why not.
If you want to end up with a List then use .collect(Collectors.toList()) instead of toArray.

How do I sort two arrays in relation to each other?

I prototype in python and I'm used the zip function for this, I'm not sure how to do this in Java. Basically I have two lists (one is names and one is data) and want them sorted in relation to each other. My program only processes a list (data, in this case) but I use the names as a reference to what data I'm processing and I want to try to experiment with processing my data in a different order. Here's an example of the structure (in reality my data is not given to me stored but I would do either a basic sort or a reverse sort on it, nothing fancy).
String[] names = new String[]{"Monkey1", "Dog2", "Horse3", "Cow4", "Spider5"};
int[] data = new int[]{1, 2, 3, 4, 5};
so the inverse would be
name = Spider5, Cow4, Horse3, Dog2, Monkey1
data = 5, 4, 3, 2, 1
I found this question: Is there an accepted Java equivalent to Python's zip(), but I would rather (if possible and for the faint of heart) do this using libraries I already have (Java commons, apache commons, etc). If there's no other way then I'll give functional java a shot. Any suggestions?
If you really don't want to redo your data-structures to combine the infos, you can use a Multimap to do it.
This example utilizes the excellent Google-Guava Library, which you should be using anyway :) https://code.google.com/p/guava-libraries/
String[] names = new String[] {"Monkey1", "Dog2", "Horse3", "Cow4", "Spider5"};
int[] data = new int[] {1,2,3,4,5};
/* guava, throws an IllegalStateException if your array aren't of the same length */
Preconditions.checkState(names.length == data.length, "data and names must be of equal length");
/* put your values in a MultiMap */
Multimap<String, Integer> multiMap = LinkedListMultimap.create();
for (int i=0; i<names.length; i++) {
mmap.put(names[i], data[i]);
}
/* our output, 'newArrayList()' is just a guava convenience function */
List<String> sortedNames = Lists.newArrayList();
List<Integer> sortedData = Lists.newArrayList();
/* cycle through a sorted copy of the MultiMap's keys... */
for (String name : Ordering.natural().sortedCopy(mmap.keys())) {
/* ...and add all of the associated values to the lists */
for (Integer value : mmap.get(name)) {
sortedNames.add(name);
sortedData.add(value);
}
}
Here's complete code:
StringIntTuple.java:
public class StringIntTuple{
public final int intValue;
public final String stringValue;
public StringIntTuple(int intValue, String stringValue){
this.intValue = intValue;
this.stringValue = stringValue;
}
public String toString(){
return "(" + this.intValue + ", " + this.stringValue + ")";
}
}
StringIntTupleStringComparator.java:
import java.util.Comparator;
public class StringIntTupleStringComparator implements
Comparator<StringIntTuple> {
#Override
public int compare(StringIntTuple a, StringIntTuple b) {
// TODO Auto-generated method stub
return a.stringValue.compareTo(b.stringValue);
}
}
StringIntTupleIntComparator.java:
import java.util.Comparator;
public class StringIntTupleIntComparator implements Comparator<StringIntTuple> {
#Override
public int compare(StringIntTuple a,
StringIntTuple b) {
return ((Integer)a.intValue).compareTo((Integer)b.intValue);
}
}
Driver.java:
import java.util.ArrayList;
import java.util.Collections;
public class Driver {
/**
* #param args
*/
public static String[] names = new String[] {"Monkey1", "Dog2", "Horse3", "Cow4", "Spider5"};
public static int[] data = new int[] {1,2,3,4,5};
public static void main(String[] args) {
ArrayList<StringIntTuple> list = new ArrayList<StringIntTuple>();
for(int i =0; i<names.length; i++){
list.add(new StringIntTuple(data[i],names[i]));
}
Collections.sort(list, new StringIntTupleIntComparator());
System.out.println(list.toString());
Collections.sort(list, new StringIntTupleStringComparator());
System.out.println(list.toString());
}
}
Output (sorted first by int field, then by String field):
[(1, Monkey1), (2, Dog2), (3, Horse3), (4, Cow4), (5, Spider5)]
[(4, Cow4), (2, Dog2), (3, Horse3), (1, Monkey1), (5, Spider5)]
EDIT 1 (extra info):
If you want to make this work for any Tuple, i.e. which doesn't constrain the field types to int, String, you can simply do the same operation with generics, i.e.:
public class Tuple<A,B>{
public Tuple(A aValue, B bValue){
this.aValue = aValue;
this.bValue = bValue;
}
public final A aValue;
public final B bValue;
}
Then, just tweak the Comparators accordingly, and you have a generic solution.
EDIT 2(After lunch): Here it is.
public class TupleAComparator<A extends Comparable<A>,B extends Comparable<B>> implements Comparator<Tuple<A,B>> {
#Override
public int compare(Tuple<A, B> t1, Tuple<A, B> t2) {
return t1.aValue.compareTo(t2.aValue);
}
}
EDIT 3: Code supplement as answer to Comment #1 (augmenting comment #2)
TupleArrayList.java:
import java.util.ArrayList;
import java.util.List;
public class TupleArrayList<A,B> extends ArrayList<Tuple<A,B>> {
/**
* An ArrayList for tuples that can generate a List of tuples' elements from a specific position within each tuple
*/
private static final long serialVersionUID = -6931669375802967253L;
public List<A> GetAValues(){
ArrayList<A> aArr = new ArrayList<A>(this.size());
for(Tuple<A,B> tuple : this){
aArr.add(tuple.aValue);
}
return aArr;
}
public List<B> GetBValues(){
ArrayList<B> bArr = new ArrayList<B>(this.size());
for(Tuple<A,B> tuple : this){
bArr.add(tuple.bValue);
}
return bArr;
}
}
So the obvious answer here is to wrap the name and data values in a class. Then maintain a List of that class. The class should implement equals, hashCode and Comparable which then then allow sorting the list using Collections.sort.
Maintain related data in two different lists is anti-OOP.
Something like this.
class MyWrapper implements Comparable<MyWrapper>{
private String name;
private int data;
}
List<MyWrapper> listToBeSorted;
The "right" way to do this in Java is to create a combined object that holds the corresponding elements, and to sort that.
Example:
class NameAndData {
private final String name;
private final int data;
}
List<NameAndData> toBeSorted;
and then you create a list of the combined elements and sort that. Basically, you're writing your own specific Pair class. (I, and many Java developers, think that adding a Pair class to Java would just lead to more obfuscated code -- a LatLong class, for example, is much less ambiguous about what it means than a Pair<Double, Double>.)
In some cases it doesn't make much sense to create a new class just to do concurrent sorting.
Here, is a function that can be used to sort an arbitrary number of Lists with arbitrary types based on a key that implement Comparable (Ideone Example here).
Usage
Here is an example of how you can use the function to sort multiple lists of arbitrary types:
// Can be any type that implements Comparable, Dupes are allowed
List<Integer> key = Arrays.asList(4, 3, 1, 2, 1);
// List Types do not need to be the same
List<String> list1 = Arrays.asList("Four", "Three", "One", "Two", "One");
List<Character> list2 = Arrays.asList('d', 'c', 'a', 'b', 'a');
// Sorts key, list1, list2
// Remove second key if you don't want to sort key.
multiSort(key, key, list1, list2);
Output:
key: [1, 1, 2, 3, 4]
list1: [One, One, Two, Three, Four]
list2: [a, a, b, c, d]
Code
An Ideone Example can be found here which includes validation of parameters and a test case.
public static <T extends Comparable<T>> void multiSort(
final List<T> key, List<?>... lists){
// Create a List of indices
List<Integer> indices = new ArrayList<Integer>();
for(int i = 0; i < key.size(); i++) {
indices.add(i);
}
// Sort the indices list based on the key
Collections.sort(indices, new Comparator<Integer>() {
#Override public int compare(Integer i, Integer j) {
return key.get(i).compareTo(key.get(j));
}
});
// Create a mapping that allows sorting of the List by N swaps.
// Only swaps can be used since we do not know the type of the lists
Map<Integer,Integer> swapMap = new HashMap<Integer, Integer>(indices.size());
List<Integer> swapFrom = new ArrayList<Integer>(indices.size()),
swapTo = new ArrayList<Integer>(indices.size());
for (int i = 0; i < key.size(); i++) {
int k = indices.get(i);
while (i != k && swapMap.containsKey(k)) {
k = swapMap.get(k);
}
swapFrom.add(i);
swapTo.add(k);
swapMap.put(i, k);
}
// use the swap order to sort each list by swapping elements
for (List<?> list : lists)
for (int i = 0; i < list.size(); i++)
Collections.swap(list, swapFrom.get(i), swapTo.get(i));
}
You could use a ConcurrentSkipListMap which can provide forward and reverse iterators over the keys. If you are looking for arbitrary re-orderings besides a fixed forward and reverse ordering, you'll have to go to something else. Or you can always keep a simple HashMap or whatever to maintain parallel item associations, and then construct a SortedMap (Treemap or ConcurrentSkipListMap) as needed by providing an appropriate Comparator.
The disadvantage of this approach is that the associations between keys/values are much more transient, and can be more easily and accidentally broken by updates to the map. All of the other answers that create Tuples, Pairs, or other explicit 1-1 relationships address that better. Of course, if you intend for the associations to be more fluid, then just using a map adds a bit of an advantage.
Assuming that the lengths of these two arrays are the same, you can create a list of map entries containing pairs of elements from these arrays, and sort this list in reverse order by key as follows:
String[] names = new String[]{"Monkey1", "Dog2", "Horse3", "Cow4", "Spider5"};
int[] data = new int[]{1, 2, 3, 4, 5};
List<Map.Entry<Integer, String>> entryList = IntStream
.range(0, names.length)
.mapToObj(i -> Map.entry(data[i], names[i]))
.sorted(Map.Entry.<Integer, String>comparingByKey().reversed())
.collect(Collectors.toList());
System.out.println(entryList);
// [5=Spider5, 4=Cow4, 3=Horse3, 2=Dog2, 1=Monkey1]
If you want to replace the contents of the arrays:
IntStream.range(0, entryList.size()).forEach(i -> {
data[i] = entryList.get(i).getKey();
names[i] = entryList.get(i).getValue();
});
System.out.println(Arrays.toString(data));
// [5, 4, 3, 2, 1]
System.out.println(Arrays.toString(names));
// [Spider5, Cow4, Horse3, Dog2, Monkey1]
See also: Sorting two parallel arrays

Java-Sorting a 2-D array quickly

I have a 2D string array consisting of values like as
{ "Home","0.1256784"
"Contact","-0.56789"
"Refer","1.36589"
"Next","3.678456" }
I have to sort the array based upon the second element(double value) and obtain a result such as like
{"Contact","-0.56789"
"Home","0.1256784"
"Refer","1.36589"
"Next","3.678456" }
I have used some bubble sort code to sort it and it works, but and i have to know how can i make the sorting more efficient than my one in faster manner.I tried some code posted previously for the questions related to mine but i can't get the task done.
My Code:
String tt="",tk="";
for(int i=1;i<myarray.length;i++)
{
for(int j=1;j<myarray.length-1;j++)
{
if(Double.parseDouble(myarray[i][1])<Double.parseDouble(myarray[j][1]))
{
tk=myarray[i][1];
tt=myarray[i][0];
myarray[i][1]=myarray[j][1];
myarray[i][0]=myarray[j][0];
myarray[j][1]=myarray;
myarray[j][0]=myarray;
}
}
}
public class Sort2D {
public static void main(String args[]) {
String ss[][] = {
{"Home", "0.1256784"},
{"Contact", "-0.56789"},
{"Refer", "1.36589"},
{"Next", "3.678456"}
};
Arrays.sort(ss, new Comparator<String[]>() {
public int compare(String[] s1, String[] s2) {
double d1 = Double.parseDouble(s1[1]);
double d2 = Double.parseDouble(s2[1]);
return Double.compare(d1, d2);
}
});
for (String[] s : ss) {
System.out.println(s[0] + ": " + s[1]);
}
}
}
If it's a 2d array you can use Array.sort(String[], Comparator<String[]> comparator) and pass a custom comparator, which compares the 2nd element of the sub array.
You can use Arrays.sortsort(Object[] a, Comparator c) and let java take care of it. You may find this link useful
Alternative approach: you could copy the data to a TreeMap (in case all double values are unique) and let the map to the sorting:
Map<Double, String> map = new TreeMap<Double, String>();
for (String[] row:myArray) {
map.put(Double.parseDouble(row[1]), row[1]);
The entrysets iterator now returns the values in ascending sort order.

Comparator interface

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);

Categories

Resources