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.
Related
Example:
d1 = "the sky is blue"
d2 = "the car is blue"
Key Value
the [<d1,1>,<d2,1>]
sky [<d1,1>]
is [<d1,1>,<d2,1>]
blue [<d1,1>,<d2,1>]
car [<d2,1>]
Where:
key = String
ex:
<d1,1>
d1 = Document id
1 = How many times the word apear on file
I created a document type object with the docid variables and frequency.
public class Documento {
private final int docid;
private final int frequencia;
public Documento(int docid, int frequencia) {
this.docid = docid;
this.frequencia = frequencia;
}
public int getDocid() {
return docid;
}
public int getFrequencia() {
return frequencia;
}
#Override
public boolean equals(Object o) {
if ((o instanceof Documento) && docid == ((Documento) o).docid && frequencia == ((Documento) o).frequencia) {
return true;
}
return false;
}
And the dictionary class that is a hashmap with
public class Dicionario {
public Map<String, Documento> indice = new HashMap<>();
public void InsereDicionario(String palavra, int docid) {
int cont = indice.containsKey(palavra) ? indice.get(palavra).getFrequencia() : 0;
indice.put(palavra, new Documento(docid, cont + 1));
}
public int frequencia(String palavra) {
return indice.get(palavra).getFrequencia();
}
public void criaDicionario(String entrada) {
String[] palavras = entrada.split("\\s+");
for (int i = 0; i < palavras.length; i++) {
InsereDicionario(palavras[i], 1);
}
}
public void ListaPalavras(){
for(String key:indice.keySet()){
System.out.println("");
}
}
But what I really need the dictionary is a list of documents , and I do not know how to do this , someone could help me ?
or is there an easier way to do this ?
If you need a list of documents, why not create one? With Java8 this becomes even more convenient:
For example:
public Map<String, List<Documento>> indice = new HashMap<>();
//register new word
indice.putIfAbsent(palavra, new ArrayList<>());
//add additional occurence
indice.get(palavra).add(documento);
//get frequency
int frequencia = indice.get(palavra)
.stream()
.map(d -> d.getFrequencia())
.reduce(0, (s, i) -> s + i);
An alternative would be to use Guava's Multimap, see here
Map<String, List<Documento>>
Obviously you need to adapt the rest of the code.
For example, when you need to add something to the dictionary, if it's the first time you need to create the List with that single document, next time you need to take the already created list and add documents there.
I am comparing two arraylist (Contacts .java is an pojo class). First Arraylist contains some Items and second arraylist contains some Items. By comparing two list, if both list contains same element it should not be added and else added to first list. But I cannot do it. Below is my code. Help will be appreciated.
public void insertmanualandxmldata()
{
mContacts = storage.getarraylist(); // Arraylist
if(mContacts != null)
{
for(int i=0; i<mContacts.size(); i++)
{
ContactVO mShareddata = mContacts.get(i);
//mParsedDataSetList arraylist
for(int j=0; j<mParsedDataSetList.size(); j++)
{
ContactVO mXmldata = mParsedDataSetList.get(j);
if(mShareddata.getNumber().contains(mXmldata.getNumber()))
{
mContacts.add(mXmldata);
}
}
}
storage.savearraylist(mContacts);
}
else
{
storage.savearraylist(mParsedDataSetList);
}
}
Implement Comparable
private class ContactsVO implements Comparable<ContactsVO>{
int number;
#Override
public int compareTo(ContactsVO that)
{
if (this.number> that.number)
return 1;
else if (this.number< that.number)
return -1;
else
return 0;
}
}
And your logic.. Add contents of list 2 to list 1. while adding we have to compare if list 1 already has that item.
for(int j=0; j < mParsedDataSetList.size(); j++)
{
ContactVO mXmldata = mParsedDataSetList.get(j);
boolean exists = false;
for(int i=0; i< mContacts.size(); i++)
{
ContactVO mShareddata = mContacts.get(i);
if(mShareddata.comprareTo(mXmldata) == 0)
{
exists = true;
break;
}
}
if(!exists)
{
mContacts.add(mXmldata);
}
}
You could implement a class that extends ArrayList and create a Comparator like this:
public static Comparator<T> Comp = new Comparator<T>(){
public int compare(Type e1, Type e2){
return (e1.getSomething().compareTo(e2.getSomething()));
}
};
If you have never used comparators before here is a good tutorial https://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
What comparators basically do is to provide a criteria for comparing elements.
There are two approaches by implementing comparator or comparable.
For your requirement I would suggest you can implements Comparable in your ContactVO class. And override compareTo method.
private class ContactsVO implements Comparable<ContactsVO> {
private Integer number;
// Remaining attributes and their getter setter.
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
#Override
public int compareTo(ContactsVO compareWith) {
if (this.getNumber() > compareWith.getNumber())
return 1;
else if (this.getNumber() < compareWith.getNumber())
return -1;
else
return 0;
}
}
If comparing attribute (in our case is number) implements Comparable then we can rewrite compareTo method as
#Override
public int compareTo(ContactsVO compareWith) {
return this.getNumber().compareTo(compareWith.getNumber());
}
Note: Some basic data types such as Integer, String implements Comparable.
Here contactList1 and contactList2 is your two list of POJO class Contacts
Set<Contacts> contactList3 = new HashSet<Contacts>(contactList1);
contactList3.addAll(contactList2);
ArrayList<Contacts> newList = new ArrayList<Contacts>(contactList3);
System.out.println("New List :"+newList);
Try to use LinkedHashSet which will not allow duplicates :
ArrayList arrayList1 = new ArrayList();
ArrayList arrayList2 = new ArrayList();
ArrayList arrayList3 = new ArrayList();
arrayList3.addAll(arrayList1);
arrayList3.addAll(arrayList2);
HashSet hashSet = new HashSet();
hashSet.addAll(arrayList3);
arrayList3.clear();
arrayList3.addAll(hashSet);
Note : when you required to maintain ordering of you list item use LinkedHashSet instead of HashSet.
I have a bean called vulnerability. It is having a column "severity".
private String severity;
Severity can hold string value High,Medium and Low. Now whenever sorting of this bean on the basis of severity column is done it happens alphabetically i.e. High,Low and Medium. But i want the sorting to happen high,medium, low when descending and low, medium,high when ascending.
I was seeing comparator to make this custom sorting but it needs to cover lots of cases. Isn't their any other way?
You can (and should) use an enum - not a String nor a int:
enum Severity {
LOW, MEDIUM, HIGH;
}
Usage:
List<Severity> lst = new ArrayList<Severity>();
lst.add(Severity.MEDIUM);
lst.add(Severity.LOW);
lst.add(Severity.HIGH);
for (Severity s : lst)
System.out.println("s = " + s);
Collections.sort(lst);
System.out.println();
for (Severity s : lst)
System.out.println("s = " + s);
OUTPUT:
s = MEDIUM
s = LOW
s = HIGH
s = LOW
s = MEDIUM
s = HIGH
EDIT
Since the OP says he can't modify the usage of Strings, we can map the strings into a comparable values:
static Map<String, Integer> severities = new HashMap<String, Integer>();
static {
severities.put("LOW",1);
severities.put("MEDIUM",2);
severities.put("HIGH",3);
}
public static void main(String[] args) {
List<String> lst = new ArrayList<String>();
lst.add("MEDIUM");
lst.add("LOW");
lst.add("HIGH");
for (String s : lst)
System.out.println("s = " + s);
Collections.sort(lst, new Comparator<String>() {
public int compare(String a1, String a2) {
Integer v1 = severities.get(a1);
Integer v2 = severities.get(a2);
return v1.compareTo(v2);
}
});
System.out.println();
for (String s : lst)
System.out.println("s = " + s);
}
and if you want to order the items in descending order you can sort and then reverse:
Collections.sort(lst);
Collections.reverse(lst);
There is an implicit compareTo operator defined on enums, which takes their declaration order to mean "smaller than". No additional code is needed.
enum Severity { Low, Medium, High }
Low.compareTo(High); // returns -1
Medium.compareTo(Low); // returns 1
However, note that the names of the enum constants will be those printed by toString() (and therefore visible to users if you echo enums directly) - if you want to use different internal and external names, possibly to uphold code conventions (say, all-caps-constants), then you will need to add an enum constructor and override the enum's toString method to use the passed-in constructor attribute.
If you cannot use enums, and you cannot change your bean
Then build a Comparator for it:
public class SeverityComparator implements Comparator<String> {
private int direction;
public SeverityComparator(boolean reverse) {
this.direction = reverse ? -1 : 1;
}
private int severity(String s) {
if (s.equals("Low")) { // you really should have constants for the values...
return 0;
} else if (s.equals("Medium")) {
return 1;
} else if (s.equals("High")) {
return 2;
} else {
throw new IllegalArgumentException("Not a severity: " + s);
}
}
#Override
public int compareTo(String other) {
return direction * (severity(this) - severity(other));
}
}
Use as
Collections.sort(listOfSeverities, new SeverityComparator(false)); // ascending
Collections.sort(listOfSeverities, new SeverityComparator(true)); // descending
#alfasin answer is correct but i would suggest using guava's Ordering:
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import javax.annotation.Nullable;
import java.util.List;
public class SeveritySortTest {
private static final List<Severity> SEVERITY_LIST = ImmutableList.copyOf(Severity.values());
public static void main(String[] args) {
Ordering<Severity> severityOrdering = Ordering.natural().onResultOf(new Function<Severity, Integer>() {
#Nullable
#Override
public Integer apply(#Nullable Severity input) {
return input.getSeverity();
}
});
List<Severity> sortedAscending = severityOrdering.sortedCopy(SEVERITY_LIST);
List<Severity> sortedDescending = severityOrdering.reverse().sortedCopy(SEVERITY_LIST);
}
enum Severity {
LOW(1), MEDIUM(2), HIGH(3);
private int severity;
Severity(int s) {
severity = s;
}
int getSeverity() {
return severity;
}
}
}
Working Solution:
Collections.sort(recommendations, new Comparator() {
private int priority(String s) {
if (s.equalsIgnoreCase("Low")) {
return 1;
} else if (s.equalsIgnoreCase("Medium")) {
return 2;
} else if (s.equalsIgnoreCase("High")) {
return 3;
} else {
return 0;
}
}
#Override
public int compare(Recommendation o1, Recommendation o2) {
return -1 * (priority(o1.getPriority()) - priority(o2.getPriority()));
}
});
If you want the DB to do this through JPA/Hibernate you could create a sort expression based on a simple case statement, assuming your entity is called Case:
Expression exp = criteriaBuilder.selectCase(root.get(Case_.priority)).when("High", 1).when("Medium", 2).otherwise(3);
queryBuilder.orderBy(orderDir.isAscending() ? criteriaBuilder.asc(exp) : criteriaBuilder.desc(exp));
Using case statements in an order by clause isn't great for performance, but solves it. Works with Oracle.
The problem is the following. There are multiple rows that have non-unique identifiers:
id value
0: {1,2,3}
0: {1,2,2}
1: {1,2,3}
2: {1,2,3}
2: {1,1,3}
I have the function equals that can compare multiple rows between each other. I need to write a code that selects the rows as an input of the function equals. The rows selected must have unique ids, BUT I should check all possible combinations of unique ids. For instance, if there are 5 rows with ids: 0,0,1,2,3, then I should check the following two combinations of ids: 0,1,2,3 and 0,1,2,3, because 0 apears twice. Of course, each of these two combinations will consist of unique rows that have id=0.
My code snippet is the following:
public class Test {
public static void main(String[] args) {
ArrayList<Row> allRows = new ArrayList<Row>();
allRows.add(new Row(0,new int[]{1,2,3}));
allRows.add(new Row(0,new int[]{1,2,2}));
allRows.add(new Row(1,new int[]{1,2,3}));
allRows.add(new Row(2,new int[]{1,2,3}));
allRows.add(new Row(2,new int[]{1,1,3}));
boolean answer = hasEqualUniqueRows(allRows);
}
private boolean hasEqualUniqueRows(ArrayList<Row> allTokens) {
for (int i=0; i<allTokens.size(); i++) {
ArrayList<Integer[]> rows = new ArrayList<Integer[]>();
rows = findUniqueRows(i,allTokens);
boolean answer = equalsExceptForNulls(rows);
if (answer) return true;
}
return false;
}
// Compare rows for similarities
public static <T> boolean equalsExceptForNulls(ArrayList<T[]> ts) {
for (int i=0; i<ts.size(); i++) {
for (int j=0; j<ts.size(); j++) {
if (i != j) {
boolean answer = equals(ts.get(i),ts.get(j));
if (!answer) return false;
}
}
}
return true;
}
public static <T> boolean equals(T[] ts1, T[] ts2) {
if (ts1.length != ts2.length) return false;
for(int i = 0; i < ts1.length; i++) {
T t1 = ts1[i], t2 = ts2[i];
if (t1 != null && t2 != null && !t1.equals(t2))
return false;
}
return true;
}
class Row {
private String key;
private Integer[] values;
public Row(String k,Integer[] v) {
this.key = k;
this.values = v;
}
public String getKey() {
return this.key;
}
public Integer[] getValues() {
return this.values;
}
}
}
Since the number of rows with unique ids is apriori unknown, I don´t know how to solve this problem. Any suggestions? Thanks.
Edit#1
I updated the code. Now it´s more complete. But it lacks the implementation of the function findUniqueRows. This function should select rows from the ArrayList that have unique keys (ids). Could someone help me to develop this function? Thanks.
Assuming the objective is to find every combination without duplicates you can do this with the following. The test to find duplicates is just to confirm it doesn't generate any duplicates in the first place.
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String... args) {
Bag<Integer> b = new Bag<>();
b.countFor(1, 2);
b.countFor(2, 1);
b.countFor(3, 3);
Set<String> set = new LinkedHashSet<>();
for (List<Integer> list : b.combinations()) {
System.out.println(list);
String s = list.toString();
if (!set.add(s))
System.err.println("Duplicate entry " + s);
}
}
}
class Bag<E> {
final Map<E, AtomicInteger> countMap = new LinkedHashMap<>();
void countFor(E e, int n) {
countMap.put(e, new AtomicInteger(n));
}
void decrement(E e) {
AtomicInteger ai = countMap.get(e);
if (ai.decrementAndGet() < 1)
countMap.remove(e);
}
void increment(E e) {
AtomicInteger ai = countMap.get(e);
if (ai == null)
countMap.put(e, new AtomicInteger(1));
else
ai.incrementAndGet();
}
List<List<E>> combinations() {
List<List<E>> ret = new ArrayList<>();
List<E> current = new ArrayList<>();
combinations0(ret, current);
return ret;
}
private void combinations0(List<List<E>> ret, List<E> current) {
if (countMap.isEmpty()) {
ret.add(new ArrayList<E>(current));
return;
}
int position = current.size();
current.add(null);
List<E> es = new ArrayList<>(countMap.keySet());
if (es.get(0) instanceof Comparable)
Collections.sort((List) es);
for (E e : es) {
current.set(position, e);
decrement(e);
combinations0(ret, current);
increment(e);
}
current.remove(position);
}
}
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.