I have fours variables that call different methods:
public String[] longestSide(){
ArrayList<T> western = getWestern();
ArrayList<T> eastern = getEastern();
ArrayList<T> northern = getNorthern();
ArrayList<T> southern = getSouthern();
return //theLongestOne??
}
Instead of writing a bunch of if-else statements, what is the shortcut to find out which of the arraylists has the longest length and return it? Thanks!
return Collections.max(Arrays.asList(western, eastern, northern, southern),
(a, b) -> Integer.compare(a.length, b.length));
If not on Java 8 yet, the same code can be written as
return Collections.max(Arrays.asList(western, eastern, northern, southern),
new Comparator<String[]> {
#Override
public int compare(String[] a, String[] b) {
return Integer.compare(a.length, b.length));
}
});
If what you have is in fact 4 List<String>, and not 4 arrays as in the original question, then it's even simpler:
return Collections.max(Arrays.asList(western, eastern, northern, southern),
Comparator.comparing(List::size));
which is equivalent to
return Collections.max(Arrays.asList(western, eastern, northern, southern),
new Comparator<List<String>> {
#Override
public int compare(List<String> a, List<String> b) {
return Integer.compare(a.size(), b.size());
}
});
Define a method as follows:
public Sting[] longestOf(String[] a, String[] b){
if(a.length>b.length) {
return a;
}
return b;
}
Now, you can do the following in your longestSide() method:
return longestOf(longestOf(western, eastern), longestOf(northern, southern));
String maxLength = Math.max(Math.max(western.length, eastern.length), Math.max(southern.length, northern.length));
String[] longest =
western.length == maxLength ? western :
eastern.length == maxLength ? eastern :
southern.length == maxLength ? southern :
northern;
return Collections.max(Arrays.asList(getWestern(), getEastern(), getNorthern(), getSouthern()), new Comparator<String[]>() {
#Override
public int compare(String[] first, String[] second) {
return first.length - second.length;
}
});
You can do it in another way.There can be some compilation problem, but the general idea is clear:
private List<T> longest;
// Decorator method, which will return array list, but will also calculate required longest direction.
public <T> List<T> calculateAndGet(List<T> list) {
if (Objects.isNull(longest) || longest.size() < list.size()) {
longest = list.size();
}
return list;
}
public String[] longestSide(){
List<T> western = calculateAndGet(getWestern());
List<T> eastern = calculateAndGet(getEastern());
List<T> northern = calculateAndGet(getNorthern());
List<T> southern = calculateAndGet(getSouthern());
return longest.toArray(new String[longest.size()]);
}
I also changed ArrayList to List. Is there any specific logic not to use "Coding to interfaces" principle?
Implementing as suggested by Shai in a comment:
public String[] longestSide(){
String[] western = getWestern();
String[] eastern = getEastern();
String[] northern = getNorthern();
String[] southern = getSouthern();
String[] longest = null;
for (String[] a : new String[][] {western,eastern,northern,southern})
if (longest == null || a.length > longest.length)
longest = a;
return longest;
}
Or using a helper method for a List (or other Collection) as indicated by updated question:
#SafeVarargs
public static <L extends Collection<?>> L longestOf(L ... lists) {
L longest = lists[0];
for (int i = 1; i < lists.length; i++)
if (lists[i].size() > longest.size())
longest = lists[i];
return longest;
}
Use like this:
return longestOf(western, eastern, northern, southern);
Related
I have a method that sorts a List by different criteria and returns the name (an instance variable) of the one with maximum value. In case more than one instance is having the maximum, all of their names should be concatenated.
Let's say I have Class A as follows.
Class A {
...
String getName(){...}
int getValue1() {...}
int getValue2() {...}
...
int getValueN() {...}
...
}
I have a List<A> listToSort. I would normally sort this list as listToSort.sort(Comparator.comparing(A::getValue1)) or listToSort.sort(Comparator.comparing(A::getValue2)), so on and so forth. Then get the ones sharing the maximum value.
In a method I believe this should be done as:
String getMaxString (Comparator c) {
listToSort.sort(c);
...
}
and send Comparator.comparing(A.getValueX) as parameter to call it with different methods. (X here indicates an arbitrary number for the getValue function).
However, I need to also return other instances sharing the same values
I will need to pass the Class methods to my method and call on instances as:
String getMaxString (Comparator c) {
listToSort.sort(c);
int maxValue = listToSort.get(listToSort.size() - 1).getValueX();
String maxString = listToSort.get(listToSort.size() - 1).getName();
for (int i = listToSort.size() - 2; i >= 0; i--) {
if (listToSort.get(i).getValueX()() == maxValue) {
maxString += ", " + listToSort.get(i).getName();
}
}
return maxString;
}
How would I pass this method to call on instances here? Or do I need to consider another way?
Edit:
I have a list of Courses as List<Course> mylist where a course can be simplified as:
Class Course {
private String name;
private int capacity;
private int students;
...
//bunch of getters.
}
My task is to return Strings for the course(es) with maximum capacity, the course(es) with maximum registered students, the course(es) with most difficulty, the maximum filled percentage, the course(es) with the maximum number of TAs etc...
Edit 2:
As requested in the comment section.
List of
Course a (name "a", capacity 10, students 5)
Course b (name "b", capacity 20, students 5)
Course c (name "c", capacity 30, students 0)
Sorting based on capacity should return "c"
Sorting based on students should return "a b"
You can pass the getter method and create the Comparator in getMaxString:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
public class Foo {
static class AClass {
private final String name;
private final int value1;
private final int value2;
String getName() { return name; }
int getValue1() { return value1; }
int getValue2() { return value2; }
public AClass(String name, int value1, int value2) {
this.name = name;
this.value1 = value1;
this.value2 = value2;
}
}
static String getMaxString(Function<AClass,Integer> f, List<AClass> listToSort) {
listToSort.sort(Comparator.comparing(f));
int maxValue = f.apply(listToSort.get(listToSort.size() - 1));
String maxString = listToSort.get(listToSort.size() - 1).getName();
for (int i = listToSort.size() - 2; i >= 0; i--) {
if (f.apply(listToSort.get(i)) == maxValue) {
maxString += ", " + listToSort.get(i).getName();
}
}
return maxString;
}
public static void main(String[] args) {
List<AClass> list = new ArrayList<>();
list.add(new AClass("a", 1,2));
list.add(new AClass("b", 1,2));
list.add(new AClass("c", 2,1));
list.add(new AClass("d", 2,1));
System.out.println(getMaxString(AClass::getValue1, list));
System.out.println(getMaxString(AClass::getValue2, list));
}
}
As Tim Moore suggested above, it isn't necessary to sort the list (which has cost O(n*log n)), we can traverse it twice:
static String getMaxString2(ToIntFunction<AClass> f, List<AClass> listToSort) {
int maxValue = listToSort.stream().mapToInt(f).max().orElseThrow();
return listToSort.stream()
.filter(a -> maxValue == f.applyAsInt(a))
.map(AClass::getName)
.collect(Collectors.joining(", "));
}
Note that you should test your code with an empty list.
It's useful to look at the type signature for Comparator.comparing, because it sounds like you want to do something similar:
static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)
The interesting part is the type of keyExtractor. Roughly speaking, it's a function from the type of the object you're comparing, to the type of the field you want to use for the comparison. In our case, these correspond to the A class and Integer. Because these types are fixed in this example, you can declare a method with a signature like this:
String getMaxString(Function<A, Integer> property)
With the existing algorithm, it can be used this way:
String getMaxString(Function<A, Integer> property) {
listToSort.sort(Comparator.comparing(property));
int maxValue = property.apply(listToSort.get(listToSort.size() - 1));
String maxString = listToSort.get(listToSort.size() - 1).getName();
for (int i = listToSort.size() - 2; i >= 0; i--) {
if (listToSort.get(i).getValueN() == maxValue) {
maxString += ", " + listToSort.get(i).getName();
}
}
return maxString;
}
However, it isn't necessary or efficient to sort the entire list in order to determine the maximum elements, as this can be determined by iterating through the list once:
String getMaxString(Function<A, Integer> property) {
int maxValue = Integer.MIN_VALUE;
StringBuilder maxString = new StringBuilder();
for (A element : listToSort) {
int currentValue = property.apply(element);
if (currentValue > maxValue) {
// there is a new maximum, so start the string again
maxString = new StringBuilder(element.getName());
maxValue = currentValue;
} else if (currentValue == maxValue) {
// equal to the existing maximum, append it to the string
if (maxString.length() > 0) {
maxString.append(", ");
}
maxString.append(element.getName());
}
// otherwise, it's less than the existing maximum and can be ignored
}
return maxString.toString();
}
Either way, you can call it using the same method reference syntax:
getMaxString(A::getValueN)
Time complexity O(n) - only one iteration through the dataset.
Hope it'll help.
If something will be unclear fill free to raise a question.
Main
public class MaxClient {
public static void main(String[] args) {
Comparator<A> comp = Comparator.comparingInt(A::getVal1);
List<A> items = List.of(new A(1, 8), new A(2, 8), new A(5, 8), new A(5, 27), new A(3, 8));
items.stream()
.collect(new GetMax(comp))
.forEach(System.out::println);
}
}
Custom collector GetMax
public class GetMax implements Collector <A, Deque<A>, Deque<A>> {
private final Comparator<A> comp;
public GetMax(Comparator<A> comp) {
this.comp = comp;
}
#Override
public Supplier<Deque<A>> supplier() {
return ArrayDeque::new;
}
#Override
public BiConsumer<Deque<A>, A> accumulator() {
return (stack, next) -> {
if (!stack.isEmpty() && comp.compare(next, stack.peekFirst()) > 0) stack.clear();
if (stack.isEmpty() || comp.compare(next, stack.peekFirst()) == 0) stack.offerLast(next);
};
}
#Override
public BinaryOperator<Deque<A>> combiner() {
return (stack1, stack2) -> {
if (stack1.isEmpty()) return stack2;
if (stack2.isEmpty()) return stack1;
if (comp.compare(stack1.peekFirst(), stack2.peekFirst()) == 0) {
stack1.addAll(stack2);
}
return stack1;
};
}
#Override
public Function<Deque<A>, Deque<A>> finisher() {
return stack -> stack;
}
#Override
public Set<Characteristics> characteristics() {
return Set.of(Characteristics.UNORDERED);
}
}
Class A that I used for testing purposes
public class A {
private int val1;
private int val2;
public A(int val1, int val2) {
this.val1 = val1;
this.val2 = val2;
}
public int getVal1() {
return val1;
}
public int getVal2() {
return val2;
}
#Override
public String toString() {
return "A val1: " + val1 + " val2: " + val2;
}
}
OUTPUT
A val1: 5 val2: 8
A val1: 5 val2: 27
Thanks for posting the information I requested. Here is what I came up with.
Create a list of Course objects
List<Course> list = List.of(
new Course("a", 10, 5),
new Course("b", 20, 5),
new Course("c", 30, 0));
Stream the methods and apply them to the list
List<String> results = Stream.<Function<Course, Integer>>of(
Course::getCapacity,
Course::getStudents)
.map(fnc-> getMaxString(fnc, list))
.toList();
results.forEach(System.out::println);
print the results
c
a b
I wrote a simple method that takes a method reference and list and finds the maximum. It does not do any sorting.
allocate a list to hold the names
set the maximum to the lowest possible
iterate thru the list applying the method.
if the value is greater than the current max replace it and clear the current list of names.
otherwise, if equal, add a new name.
once done, return the formatted string.
static String getMaxString(Function<Course, Integer> fnc,
List<Course> list) {
List<String> result = new ArrayList<>();
int max = Integer.MIN_VALUE;
for (Course obj : list) {
int val = fnc.apply(obj);
if (val >= max) {
if (val > max) {
result.clear();
}
max = val;
result.add(obj.getName());
}
}
return String.join(" ", result);
}
I am trying to rearrange an ArrayList based on the name of the items to be on specific index.
My list currently is this:
"SL"
"TA"
"VP"
"SP"
"PR"
and i want to rearrange them to:
"SL"
"SP"
"TA"
"PR"
"VP"
but based on the name and not in the index.
I have tried this:
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("SL")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("SP")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("TA")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("PR")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("VP")){
orderedDummyJSONModelList.add(list.get(i));
}
}
and it works fine, but i want to know if there is a more efficient way to do in 1 for loop or maybe a function. I do not wish to do it like this:
orderedDummyJSONModelList.add(list.get(0));
orderedDummyJSONModelList.add(list.get(3));
orderedDummyJSONModelList.add(list.get(1));
orderedDummyJSONModelList.add(list.get(4));
orderedDummyJSONModelList.add(list.get(2));
Which also works. Any ideas?
You can use Collection.Sort method as Collection.Sort(list) since list is a List<String> you will be fine. But if you want to implement a new comparator:
Collections.sort(list, new NameComparator());
class NameComparator implements Comparator<String> { //You can use classes
#Override
public int compare(String a, String b) { //You can use classes
return a.compareTo(b);
}
}
EDIT:
You can define a class comparator for your needs:
class ClassComparator implements Comparator<YourClass> { //You can use classes
#Override
public int compare(YourClass a, YourClass b) { //You can use classes
return a.name.compareTo(b.name);
}
}
The key thing here is: you need to get clear on your requirements.
In other words: of course one can shuffle around objects stored within a list. But: probably you want to do that programmatically.
In other words: the correct approach is to use the built-in Collection sorting mechanisms, but with providing a custom Comparator.
Meaning: you better find an algorithm that defines how to come from
"SL"
"TA"
"VP"
"SP"
"PR"
to
"SL"
"SP"
"TA"
"PR"
"VP"
That algorithm should go into your comparator implementation!
The point is: you have some List<X> in the first place. And X objects provide some sort of method to retrieve those strings you are showing here. Thus you have to create a Comparator<X> that works on X values; and uses some mean to get to those string values; and based on that you decide if X1 is <, = or > than some X2 object!
hereĀ“s an answer just specific for your problem working just for the given output. If the List contains anything else this might break your ordering, as there is no rule given on how to order it and the PR just randomly appears in the end.
public static void main(String[] args) {
List<String> justSomeNoRuleOrderingWithARandomPRInside = new ArrayList<String>();
justSomeNoRuleOrderingWithARandomPRInside.add("SL");
justSomeNoRuleOrderingWithARandomPRInside.add("TA");
justSomeNoRuleOrderingWithARandomPRInside.add("VP");
justSomeNoRuleOrderingWithARandomPRInside.add("SP");
justSomeNoRuleOrderingWithARandomPRInside.add("PR");
java.util.Collections.sort(justSomeNoRuleOrderingWithARandomPRInside, new NameComparator());
for(String s : justSomeNoRuleOrderingWithARandomPRInside) {
System.out.println(s);
}
}
static class NameComparator implements Comparator<String> { //You can use classes
#Override
public int compare(String a, String b) { //You can use classes
// Lets just add a T in front to make the VP appear at the end
// after TA, because why not
if (a.equals("PR")) {
a = "T"+a;
} else if(b.equals("PR")) {
b = "T"+b;
}
return a.compareTo(b);
}
}
O/P
SL
SP
TA
PR
VP
But honestly, this solution is crap, and without any clear rule on how to order these this will be doomed to fail as soon as you change anything as #GhostCat tried to explain.
How about this
// define the order
List<String> ORDER = Arrays.asList("SL", "SP", "TA", "PR", "VP");
List<MyObject> list = ...
list.sort((a, b) -> {
// lamba syntax for a Comparator<MyObject>
return Integer.compare(ORDER.indexOf(a.getString()), ORDER.indexOf(b.getString());
});
Note that this will put any strings that aren't defined in the ORDER list at the start of the sorted list. This may or may not be acceptable - it may be worth checking that only valid strings (i.e. members of ORDER) appear as the result of MyObject.getString().
Use a hashmap to store the weight of all strings (Higher the value of the hashmap means the later this string should come in the final list).
Using a Hashmap, so you can expand it later for other strings as well. It'll be easier to enhance in future.
Finally, Use a custom Comparator to do it.
Required Setup:
List<String> listOfStrings = Arrays.asList("SL", "TA", "VP", "SP", "PR");
HashMap<String, Integer> sortOrder = new HashMap<>();
sortOrder.put("SL", 0);
sortOrder.put("TA", 1);
sortOrder.put("VP", 2);
sortOrder.put("SP", 3);
sortOrder.put("PR", 4);
Streams:
List<String> sortedList = listOfStrings.stream().sorted((a, b) -> {
return Integer.compare(sortOrder.get(a), sortOrder.get(b));
}).collect(Collectors.toList());
System.out.println(sortedList);
Non-Stream:
Collections.sort(listOfStrings, (a, b) -> {
return Integer.compare(sortOrder.get(a), sortOrder.get(b));
});
OR
listOfStrings.sort((a, b) -> {
return Integer.compare(sortOrder.get(a), sortOrder.get(b));
});
System.out.println(listOfStrings);
Output:
[SL, TA, VP, SP, PR]
You can build an index map using a LinkedHashMap. This will be used to lookup the order which to sort using the category names of your items.
ItemSorting
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ItemSorting {
public static void main(String[] args) {
List<Item> list = new ArrayList<Item>();
IndexMap indexMap = new IndexMap("SL", "SP", "TA", "PR", "VP");
ItemComparator itemComparator = new ItemComparator(indexMap);
list.add(new Item("SL"));
list.add(new Item("TA"));
list.add(new Item("VP"));
list.add(new Item("SP"));
list.add(new Item("PR"));
Collections.sort(list, itemComparator);
for (Item item : list) {
System.out.println(item);
}
}
}
ItemComparator
import java.util.Comparator;
public class ItemComparator implements Comparator<Item> {
private IndexMap indexMap;
public IndexMap getIndexMap() {
return indexMap;
}
public void setIndexMap(IndexMap indexMap) {
this.indexMap = indexMap;
}
public ItemComparator(IndexMap indexMap) {
this.indexMap = indexMap;
}
#Override
public int compare(Item itemA, Item itemB) {
if (itemB == null) return -1;
if (itemA == null) return 1;
if (itemA.equals(itemB)) return 0;
Integer valA = indexMap.get(itemA.getCategoryName());
Integer valB = indexMap.get(itemB.getCategoryName());
if (valB == null) return -1;
if (valA == null) return 1;
return valA.compareTo(valB);
}
}
IndexMap
import java.util.LinkedHashMap;
public class IndexMap extends LinkedHashMap<String, Integer> {
private static final long serialVersionUID = 7891095847767899453L;
public IndexMap(String... indicies) {
super();
if (indicies != null) {
for (int i = 0; i < indicies.length; i++) {
this.put(indicies[i], new Integer(i));
}
}
}
}
Item
public class Item {
private String categoryName;
public Item(String categoryName) {
super();
this.categoryName = categoryName;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((categoryName == null) ? 0 : categoryName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Item other = (Item) obj;
if (categoryName == null) {
if (other.categoryName != null) return false;
} else if (!categoryName.equals(other.categoryName)) return false;
return true;
}
#Override
public String toString() {
return String.format("Item { \"categoryName\" : \"%s\" }", categoryName);
}
}
Result
Item { "categoryName" : "SL" }
Item { "categoryName" : "SP" }
Item { "categoryName" : "TA" }
Item { "categoryName" : "PR" }
Item { "categoryName" : "VP" }
You coud define a helper method like this one:
public static int get(String name) {
switch (name) {
case "SL":
return 1;
case "SP":
return 2;
case "TA":
return 3;
case "PR":
return 4;
case "VP":
return 5;
default:
return 6;
}
}
and write in your main method something like:
ArrayList<String> al = new ArrayList<>();
al.add("SL");
al.add("TA");
al.add("VP");
al.add("SP");
al.add("PR");
Collections.sort(al, (o1, o2) -> return get(o1) - get(o2); );
al.forEach((s) -> System.out.println(s));
You can create a Map that maintains the position. When you iterate through the unordered list just get the position of that string value and insert into new array(not arraylist), then later if required you can convert that array to ArrayList.
Example code:
Map<String,Integer> map = new HashMap<>(); //you can may be loop through and make this map
map.put("SL", 0);
map.put("SP", 1);
map.put("TA",2);
map.put("PR",3);
map.put("VP",3);
List<String> list1 // your unordered list with values in random order
String[] newArr = new String[list1.size()];
for(String strName: list1){
int position = map.get(strName);
arr[position] = strName;
}
//newArr has ordered result.
I created arrayList with this values
ArrayList<String> list = new ArrayList<>();
list.add("a.b.c");
list.add("a.b.d");
list.add("a.b.e.f");
list.add("a.b.e.h");
I want to so sorting according to the number of '.'s in the string.
That is, the string that has the minimum number of '.'s will become the first one.
I tried to do this,
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) {
return findDot(a) - findDot(b)
}
private findDot(String a ){
String [] result = a.split("\\.")
return result .length
}
});
But it didn't work.
Did I miss something ?
Your source code is wrong(it contains syntax error).
The right code is below:(It works but better code exists)
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) {
return Integer.compare(findDot(a), findDot(b));
}
private int findDot(String a ){
String [] result = a.split("\\.");
return result.length;
}
});
And I advise you that if you use compare, use Integer.compare(A, B) instead A - B because if A is too big and B is too small(e.g. -2918291) then A - B is overflow and it raise an error.
Works fine for me. The only thing you were missing was a return type for the method findDot and a couple semi-colons, and the space between results .length
import java.util.Collections;
import java.util.Comparator;
public class Hello {
/**
* #param args
*/
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("a.b.e.h");
list.add("a.b.c");
list.add("a.b.e.f.h.g");
list.add("a.b.d");
list.add("a.b.e.f");
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) {
return findDot(a) - findDot(b);
}
private int findDot(String a ){
String [] result = a.split("\\.");
return result.length;
}
});
for (String s : list) {
System.out.println(s);
}
}
}
Output
a.b.c
a.b.d
a.b.e.h
a.b.e.f
a.b.e.f.h.g
If you just want it sorted the other way around, just change this
return findDot(a) - findDot(b);
to this
return findDot(b) - findDot(a);
private findDot(String a ){
String [] result = a.split("\\.")
return result .length
}
Change it as
private int findDot(String a){
String [] result = a.split("\\.");
return result.length;
}
I have ArrayList it contains so many arrays, each array contain first name, last name. now I want to sort the list based on the last name.
Example:
ArrayList<String[]> list=new ArrayList<String[]>();
String[] name1={"koti" ,"reddy"};
String[] name2={"hanu" ,"sanjay"};
String[] name3={"ajay" ,"zedeja"};
String[] name4={"basha" ,"kadhar"};
list.add(name1);
list.add(name2);
list.add(name3);
list.add(name4);
I want the sorting order like:
basha kadhar
koti reddy
hanu sanjay
ajay zedeja
Could you please help on this ASAP, Thanks in Advance
Write a custom Comparator and supply that to the appropriate sort overload along with the data.
However, I would recommend a separate Person/Name type, instead of String arrays, as it will make data easier to keep track of and it could implement Comparable (which would eliminate/replace the need of a Comparator).
Now, when writing an applicable compare/compareTo, the code should look similar to:
int cmpLastName = a_lastName.compareTo(b_lastName);
if (cmpLastName == 0) {
// same lastname, order now based on first name
return a_firstName.compareTo(b_firstName);
} else {
// different lastname, so have enough ordering
return cmpLastName;
}
try this
Collections.sort(list, new Comparator<String[]>() {
#Override
public int compare(String[] o1, String[] o2) {
int c = o1[0].compareTo(o2[0]);
if (c != 0) {
return c;
}
return o1[1].compareTo(o2[1]);
}
});
This is how I would perform that sort operation.
public static void main(String[] args) {
ArrayList<String[]> list = new ArrayList<String[]>();
String[] name1 = { "koti", "reddy" };
String[] name2 = { "hanu", "sanjay" };
String[] name3 = { "ajay", "zedeja" };
String[] name4 = { "basha", "kadhar" };
list.add(name1);
list.add(name2);
list.add(name3);
list.add(name4);
System.out.println("Before sorting");
for (String[] r : list) {
System.out.println(Arrays.toString(r));
}
Collections.sort(list, new Comparator<String[]>() {
public int compare(String[] left, String[] right) {
if (left == null) { // null?
if (right == null) { // null == null!
return 0;
}
return -1; // null < not(null)
} else if (right == null) {
return 1; // not(null) > null.
}
// If the last names aren't the same, return the result
// of comparing the last names.
if (left[1].compareTo(right[1]) != 0) {
return left[1].compareTo(right[1]);
}
// Return the result of comparing the first names.
return left[0].compareTo(right[0]);
}
});
System.out.println("After sorting");
for (String[] r : list) {
System.out.println(Arrays.toString(r));
}
}
try this code to achieve your output.
public static void main(String []args){
ArrayList<String[]> list=new ArrayList<String[]>();
String[] name1={"koti" ,"reddy"};
String[] name2={"hanu" ,"sanjay"};
String[] name3={"ajay" ,"zedeja"};
String[] name4={"basha" ,"kadhar"};
list.add(name1);
list.add(name2);
list.add(name3);
list.add(name4);
Collections.sort(list, new Comparator<String[]>() {
#Override
public int compare(String[] s1, String[] s2) {
int i = s1[0].compareTo(s2[0]);
if (i != 0) {
return i;
}
return s1[1].compareTo(s2[1]);
}
});
System.out.println("after sorting"+"\n");
for (String[] s : list) {
for(int i=0;i<s.length;i++){
System.out.print(s[i]+"\t");
}
System.out.print("\n");
}
}
private List<String> subList;
private List<List<String>> records = new ArrayList<List<String>>();
for(....){
subList = new ArrayList<String>();
...populate..
records.add(subList);
}
For example, subList has three Strings - a, b, and c.
I want to sort the records by the value of b in subList.
records at 0 has a list of "10", "20", "30"
records at 1 has a list of "10", "05", "30"
records at 2 has a list of "10", "35", "30"
After the sort, the order of records should be -
records at 0 = records at 1 above
records at 1 = records at 0 above
records at 2 = records at 2 above
What could be a good algorithm for that?
Something like:
Collections.sort(records, new Comparator<List<String>>()
{
public int compare(List<String> o1, List<String> o2)
{
//Simple string comparison here, add more sophisticated logic if needed.
return o1.get(1).compareTo(o2.get(1));
}
})
Though I find hard-coding the positions a little dubious in practice, your opinion may differ.
This is just like sorting a string of characters: given two strings, start at the beginning and compare each character; if there's a difference, the string with the lower value comes first, otherwise, look at the next characters from each string. If the strings are of different lengths, treat the shorter string as if it had a suffix of zeroes.
In this case, the "characters" are integer values, obtained by calling Integer.parseInt(). Additionally, implementing a Comparator for a List<String> would be helpful here. Then the Collections.sort() method can be used.
The comparator might look something like this:
final class MyComparator implements Comparator<List<String>> {
public int compare(List<String> a, List<String> b) {
/* Assume all strings are parseable to values
* in range [0,Integer.MAX_VALUE] */
int len = Math.min(a.size(), b.size());
for (int idx = 0; idx < len; ++idx) {
int va = Integer.parseInt(a.get(idx)), vb = Integer.parseInt(b.get(idx));
if (va != vb)
return va - vb;
}
return va.size() - vb.size();
}
#Override
public boolean equals(Object o) {
return o instanceof MyComparator;
}
#Override
public int hashCode() {
return MyComparator.class.hashCode();
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MyList
{
private List<List<Long>> myList;
public MyList()
{
myList = new ArrayList<List<Long>>();
ArrayList arrayList = null;
for(int i=0;i<3;i++)
{
arrayList = new ArrayList<Long>();
for(int x=0;x<3;x++)
{
arrayList.add((Long)Math.round(Math.random()*10));
}
myList.add(arrayList);
}
}
public static void main(String[] args)
{
MyList newList = new MyList();
newList.printList();
Collections.sort(newList.getMyList(),new Comparator<List<Long>>(){
public int compare(List<Long> o1, List<Long> o2) {
if(o1 != null && o2 !=null)
{
Long var1 = o1.get(0);
Long var2 = o2.get(0);
return var1.compareTo(var2);
}
return 0;
}
});
newList.printList();
}
private void printList() {
for(List<Long> subString : myList)
{
System.out.println("List");
for(Long elements : subString)
{
System.out.println(elements);
}
}
}
public List<List<Long>> getMyList() {
return myList;
}
public void setMyList(List<List<Long>> myList) {
this.myList = myList;
}
}
The Column Comparator allows your to sort on any column within the List. The sort is done using the natural sort order of the data in the column.