I have values in linked list as
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
Pranish,pranishfilan,viper,1234
zxs,asdf,asfd,1234
uv,vr,va,1234
www,dsf,ASDF,123
dsfgsdf,sd,sd,235
The values are seperated by commas which contains certain data. The first ones i.e TY12354d, TY12345saf, Pranish etc are the id, second i.e sfasdf, asdffasd, pranishfilan, etc are name.The values are viewed in jtextfield. I want to enable user to sort the datas according to the id when he clicks on "sort by id" button, name when he clicks on "sort by name" button and so on.
Try this one to sort by id.
LinkedList<String> list = new LinkedList<String>();
list.add("TY12354d,sfasdf,asfasf,2.35123412E8");
list.add("TY12354dsaf,asdffasd,asfasfafsd,12344.0");
list.add("Pranish,pranishfilan,viper,1234");
list.add("zxs,asdf,asfd,1234");
list.add("uv,vr,va,1234");
list.add("www,dsf,ASDF,123");
list.add("dsfgsdf,sd,sd,235");
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) {
System.out.println(a+" --> "+b);
return a.substring(0, a.indexOf(',')).compareTo(b.substring(0, b.indexOf(',')));
}
});
Use same concept for name also.
output:
Pranish,pranishfilan,viper,1234
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
dsfgsdf,sd,sd,235
uv,vr,va,1234
www,dsf,ASDF,123
zxs,asdf,asfd,1234
--EDIT--
as per OP last comment to compare on Car object
class Car {
String id;
String name;
public Car(String id, String name) {
this.id = id;
this.name = name;
}
// getter & setter
}
LinkedList<Car> list = new LinkedList<Car>();
list.add(new Car("TY12354d", "sfasdf"));
list.add(new Car("TY12354dsaf", "asdffasd"));
list.add(new Car("Pranish", "pranishfilan"));
list.add(new Car("zxs", "asdf"));
list.add(new Car("uv", "vr"));
list.add(new Car("www", "dsf"));
list.add(new Car("dsfgsdf", "sd"));
Collections.sort(list, new Comparator<Car>() {
public int compare(Car c1, Car c2) {
return c1.id.compareTo(c2.id);
}
});
You'll have to write your own comparator, or rewrite the structure. With a comparator you can simply use Collections.sort to sort the list.
There are many threads on implementing comparators here on stackoverflow, like this one. It's actually fairly simple.
It's not very efficient to sort a linked list, so if you don't use Collections.sort, which uses an intermediate array to sort, I'd suggest that you change your datastructure to e.g. an array or ArrayList. Or, even better: create a Class to represent your data and define comparators for that class.
Here's an example of a Comparator:
import java.util.*;
class Test {
static class IDComparator implements Comparator<String> {
#Override
public int compare(String a, String b) {
return a.split(",")[0].compareToIgnoreCase(b.split(",")[0]);
}
}
public static void main(String[] args) {
LinkedList<String> ll = new LinkedList<String>();
ll.add("TY12354d,sfasdf,asfasf,2.35123412E8");
ll.add("TY12354dsaf,asdffasd,asfasfafsd,12344.0");
ll.add("Pranish,pranishfilan,viper,1234");
System.out.println("Before sorting on ID:\n");
for (String s : ll) {
System.out.println(s);
}
Collections.sort(ll,new IDComparator());
System.out.println("\nAfter sorting on ID:\n");
for (String s : ll) {
System.out.println(s);
}
}
}
Output:
Before sorting on ID:
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
Pranish,pranishfilan,viper,1234
After sorting on ID:
Pranish,pranishfilan,viper,1234
TY12354d,sfasdf,asfasf,2.35123412E8
TY12354dsaf,asdffasd,asfasfafsd,12344.0
This is not the prettiest code I've written. I especially don't like the comparator itself, with a hard coded index. However, it'll give you an idea of how to proceed with custom comparators.
Related
how to implement Java Based Auto suggestion. suppose I have different types of data like firstName, rollNumber, address.
My first requirement is like if user enter first character on text box, then result should be sorted on natural order based on firstName and 10 results should be display.
after space if use enter second character and if it is numbere then RollNumber else lastName should be sorted on natural order as ascending.
or if user type third character then Address should be display on ascending order. there should be no database, you don't have to implement Solr or other api. how to implement on pure Java.
here I did not implement the text-box,but I Just took an example to demonstrate
import java.util.*;
import java.lang.*;
import java.io.*;
// A class to represent a student.
class Student {
int rollno;
String name;
String address;
// Constructor
public Student(int rollno, String name, String address) {
this.rollno = rollno;
this.name = name;
this.address = address;
}
// Used to print student details in main()
public String toString(){
return this.rollno + " " + this.name +
" " + this.address;
}
}
class Sortbyroll implements Comparator<Student> {
// Used for sorting in ascending order of rollno
public int compare(Student a, Student b) {
return a.rollno - b.rollno;
}
}
class Sortbyname implements Comparator<Student> {
// Used for sorting in ascending order of name
public int compare(Student a, Student b) {
return a.name.compareTo(b.name);
}
}
// Driver class
class Main {
public static void main (String[] args) {
ArrayList<Student> ar = new ArrayList<Student>();
//here I have thousand student are inserted into
//simple collection.
ar.add(new Student(111, "bbbb", "london"));
ar.add(new Student(131, "aaaa", "nyc"));
ar.add(new Student(121, "cccc", "jaipur"));
System.out.println("Unsorted");
for (int i=0; i<ar.size(); i++) {
System.out.println(ar.get(i));
}
//collection sorted by rollno
Collections.sort(ar, new Sortbyroll());
System.out.println("\nSorted by rollno");
for (int i=0; i<ar.size(); i++) {
System.out.println(ar.get(i));
}
//sort by Name
Collections.sort(ar, new Sortbyname());
System.out.println("\nSorted by name");
for (int i=0; i<ar.size(); i++) {
System.out.println(ar.get(i));
}
}
}
First of all your question is incomplete and misleading. It does not describes the requirement properly. But overall what I assume
You want Google like (?) suggester in your text box
It does not tell any specific things. What about your front end ? How about your data ?
Any way I think you just wanted to have a console like application where you will give partial String as input and your method will guess the Rest of String as an assumption from your dummy data. Am I right ?
If that is the thing you were looking for then I just sketched a demo code below
static List<String> query(String queryStr, List<Student> list) {
List<String> suggestion = new ArrayList<>();
list.forEach(std -> {
if (isMatched(queryStr, String.valueOf(std.getRoll()))) {
suggestion.add(String.valueOf(std.getRoll()));
}
if (isMatched(queryStr, std.getName())) {
suggestion.add(std.getName());
}
if (isMatched(queryStr, std.getAddress())) {
suggestion.add(std.getAddress());
}
});
return suggestion;
}
private static boolean isMatched(String query, String text) {
return text.toLowerCase().contains(query.toLowerCase());
}
And what does this code do ? It actually takes the Partial String that the user input so far and your List<Student> as parameters. Then it iterates over the list and matches for all field for partial match. If any field matches the query it add that value in the suggestion list. In the main you can do like this :
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student(101, "Abc ghi", "USA"));
list.add(new Student(102, "DEF", "UST"));
list.add(new Student(103, "Ghi ab", "DSjkD"));
list.add(new Student(104, "jKL ut", "USN"));
list.add(new Student(105, "MNP", "TSA101"));
list.add(new Student(106, "UTC ABC", "ESA"));
List<String> sugg = query("01", list);
sugg.forEach(System.out::println);
}
and you will find the console printed like :
101
TSA101
Does it make sense ? it might not be your whole confusing requirements. But I think you got the idea. You can exploit this to address your own requirements. You could further imply your sorting logic or any kind of filters to it. It should not be that tough thing.
But you should be concerned that with large number of collection or complex associated objects this would not suffice. Real world application does not work this straight forward. You might need lot of other things to consider like memory, i/o and execution time.
Good Luck!
Do refer https://github.com/nikcomestotalk/autosuggest/
This implementation is in java based on Patricia trie and Edit distance algorithm.
Some salient features of this application is
Auto correction of keywords
Bucket support for sorting and personalization support.
Filtering support.
Limit support.
Build in http server.
Blazing fast search.
And you all are welcome for feedback
Solr/Lucene/Elastic will not give freedom to choose algorithm and personalization support.
You can use a Trie data structure for autosuggestion implementation and the time complexity would be O(word_length) for insert and search.
Apache commons provides implementation "org.apache.commons.collections4.Trie"
example:
Trie<String, String> trie = new PatriciaTrie<>();
trie.put("abcd", "abcd");
trie.put("abc", "abc");
trie.put("abef", "abef");
SortedMap<String, String> map = trie.prefixMap("ab");
map.forEach((k, v) -> {
System.out.println(k + " " + v);
});
I am currently trying to order an ArrayList of String elements (called myarraylist) according to the numbers found after the word "Item". Here is a snippet of what is in myarraylist:
Item 1
Item 2
Item 3
...
Item 9
Item 10
I would like to order myarraylist to the following order:
Item 10
Item 9
Item 8
...
Item 3
Item 2
Item 1
So far, this is what I have tried:
Collections.sort(myarraylist, String.CASE_INSENSITIVE_ORDER);
Collections.reverse(myarraylist);
However, this orders the myarraylist in the following order
Item 9
Item 8
...
Item 3
Item 2
Item 10
Item 1
As you can see, Item 10 is out of place, because it reads "10" by its first number, "1". Does anyone know how to appropriately order myarraylist in reverse numerical order?
That's because the default String Comparator uses lexicographical order -- i.e. character by character, as in a dictionary. Since "1" comes before "2", any String starting with "1" will precede any other starting with "2".
You should use a custom comparator to implement Natural Sorting. A good example would be Alphanum, from Dave Koelle, which you would use like this:
Collections.sort(myarraylist, new AlphanumComparator());
I use this simple class to order my Strings:
public abstract class StringOrderer {
public static ArrayList<String> order(ArrayList<String> items, boolean ascending) {
Collections.sort(items, new StringComparator());
// reverse the order
if(!ascending) Collections.reverse(items);
return items;
}
class StringComparator implements Comparator<String> {
#Override
public int compare(String s1, String s2) {
// use the users default locale to sort the strings
Collator c = Collator.getInstance(Locale.getDefault());
return c.compare(s1, s2);
}
}
}
The basic idea is that i have a custom Comparator that uses the default Locale.
Since you are using String in the Array list it alway checks characters. Better you try using Integer. It may works for you.
As String can not be extended, it is better to change ArrayList<String> to ArrayList<ClassWithStringAttribute> then implement Comparable in ClassWithStringAttribute when you need custom comparison. For your particular case and illustration, the following class should work, though not a nice approach.
myarraylist= StringSorter.getSortedList(myarraylist);
Will give you a sorted list
public class StringSorter implements Comparable<StringSorter>{
String tempString;
public StringSorter(String data) {
this.tempString = data;
}
public static List<String> getSortedList(List<String> unsortedList){
List<StringSorter> tempList=new ArrayList<StringSorter>();
for (String current : unsortedList) {
tempList.add(new StringSorter(current));
}
Collections.sort(tempList);
List<String> sortedString=new ArrayList<String>();
for (StringSorter current : tempList) {
sortedString.add(current.tempString);
}
return sortedString;
}
#Override
public int compareTo(StringSorter other) {
Integer otherInt=Integer.parseInt(other.tempString.replaceFirst("Item ", ""));
Integer thisInt=Integer.parseInt(this.tempString.replaceFirst("Item ", ""));
if(otherInt>thisInt){
return -1;
}else if(otherInt<thisInt){
return 1;
}else{
return 0;
}
}
}
How about this custom Comparator,
public class StringNumSuffixComparator implements Comparator<String>{
#Override
public int compare(String o1, String o2) {
String str1 = o1;
String str2 = o2;
Integer num1 = Integer.parseInt(str1.replaceAll("\\D+",""));
Integer num2 = Integer.parseInt(str2.replaceAll("\\D+",""));
return num2.compareTo(num1);
}
}
To sort them with Collections.sort(),
Collections.sort(items, new StringNumSuffixComparator());
I have an arraylist defined whose elements are say, [man, animal, bird, reptile]. The elements in the arraylist are non-mandatory. The list can even be empty.
I always need to give the output as [animal,man,reptile,bird]. Means, the order of the elements are to be maintained. Is there any way of doing in arraylist?
I thought I can do like
for (String listElement: customList) { //custom list variable holds all elements
if (listElement.equalsIgnoreCase("animal"){
newList.add(0, listElement);
} else if("man") {
newlist.add(1, listElement);
}
But I would want to know the best practice of doing. Can someone please help me on this?
You can define a custom sorting and use it to order your array (save the comparator somewhere, so you don't have to instantiate it many times):
List<String> definedOrder = // define your custom order
Arrays.asList("animal", "man", "reptile", "bird");
Comparator<String> comparator = new Comparator<String>(){
#Override
public int compare(final String o1, final String o2){
// let your comparator look up your car's color in the custom order
return Integer.valueOf(definedOrder.indexOf(o1))
.compareTo(Integer.valueOf(definedOrder.indexOf(o2)));
}
};
Collections.sort(myList, comparator);
Use a custom comparator:
Collections.sort(customList, comparator);
int i = 0;
for (String temp : customList) {
System.out.println("customList " + ++i + " : " + temp);
}
Custom comparator below:
public static Comparator<String> comparator = new Comparator<String>() {
public int compare(String str1, String str2) {
return orderOf(str1) - orderOf(str2);
}
private int orderOf(String name) {
return ((List)Arrays.asList("animal", "man", "reptile", "bird")).indexOf(name);
}
};
You can use Collections.sort(yourArrayList, new CustomComparator());
You need to create your own comparator for this, though, but it is easy.
public class CustomComparator implements Comparator<YourType>{
#Override
public int compare(YoyrType o1, YoyrType o2) {
// logic for ordering the list
}
}
arraylist is ordered.
maybe you want to insert element into the list.
could you create a new list every time when you have to insert and copy each of them?
I have an ArrayList that consists of an ArrayList that constists of Strings: ArrayList<ArrayList<String>>. How can I sort on the first entry of he inner ArrayList? For example I would like this:
a = [['1','apple'],['3','pear'],['2','banana'],['1',orange']]
to become:
a_sorted = [['1','apple'],['1','orange'],['2','banana'],['3','pear']]
The order of duplicate first entries (like apple and orange) do not matter. I've tried using Collections.sort(a,new ColumnComparator()) but it will not accept ArrayLists. This is the class I used:
public class ColumnComparator implements Comparator<ArrayList<String>>{
public int compare(ArrayList<String> ar1, ArrayList<String> ar2){
return ar1.get(0).compareTo(ar2.get(0));
}
}
Instead of storing an Array of an Array, why don't you create a custom Class that implements Comparable. eg.
class Fruit implements Comparable<Fruit> {
protected int number;
protected String name;
public Fruits(int number, String name) {
this.number = number;
this.name = name;
}
#Override
public int compareTo(Fruit f) {
return number < f.number;
// or depending on if ascending or descending order wanted
// return number > f.number
}
}
Then to sort just run Collections.sort(a). This way is flexible and easily extended.
You can create a Map <String, ArrayList<String>> with first entry of the ArrayLists as key and the ArrayList itself as value. Then sort the Map (use Sorted Map or a Comparator to sort on the Map keys) on keys and you will get what you want.
Why cant you use a this ArrayList<Map<String,String>> instead of ArrayList<ArrayList<String>>. You can easily sort the Map on the key by using TreeMap.
Note: This will only work if you have only two entries in your inner arraylist.
If you really want to do it that way, you can try this:
import java.util.Comparator;
public class ColumnComparable implements Comparator<ArrayList<String>>{
#Override
public int compare(ArrayList<String> o1, ArrayList<String> o2) {
return (Integer.parseInt(o1.get(0)) > Integer.parseInt(o2.get(0)) ? -1 : (Integer.parseInt(o1.get(0)) == Integer.parseInt(o2.get(0)) ? 0 : 1));
}
}
The code was found here.
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);