What is the "good" (and why ?) solution to get a List from a Set and sorted against a given Comparator ?
Set<Object> set = new HashSet<Object>();
// add stuff
List<Object> list = new ArrayList<Object>(set);
Collections.sort(list, new MyComparator());
Just construct it. The ArrayList has a constructor taking another Collection.
Set<Foo> set = new TreeSet<Foo>(new FooComparator<Foo>());
// Fill it.
List<Foo> list = new ArrayList<Foo>(set);
// Here's your list with items in the same order as the original set.
Either:
Set<X> sortedSet = new TreeSet<X>(comparator); ...
List<X> list = new ArrayList<X>(sortedSet);
or:
Set<X> unsortedSet = new HashSet<X>(); ...
List<X> list = new ArrayList<X>(unsortedSet);
Collections.sort(list, comparator);
Assuming that you start with an unsorted set or a set sorted on a different order, the following is probably the most efficient assuming that you require a modifiable List.
Set<T> unsortedSet = ...
List<T> list = new ArrayList<T>(unsortedSet);
Collections.sort(list, comparator);
If an unmodifiable List is acceptable, then the following is a bit faster:
Set<T> unsortedSet = ...
T[] array = new T[unsortedSet.size()];
unsortedSet.toArray(array);
Arrays.sort(array, comparator);
List<T> list = Arrays.asList(array);
In the first version, Collections.sort(...) copies the list contents to an array, sorts the array, and copies the sorted elements back to the list. The second version is faster because it doesn't need to copy the sorted elements.
But to be honest the performance difference is probably not significant. Indeed, as the input set sizes get larger, the performance will be dominated by the O(NlogN) time to do the sorting. The copying steps are O(N) and will reduce in importance as N grows.
This is how you get a List when you have a Set:
List list = new ArrayList(set);
Not sure what you expect to do with the Comparator. If the Set is sorted, the list will contain the elements in sorted order.
Related
{ "744101", "744101","744101", "744102",744102","744102","744102","744102","744103","744103"}
List<String> list2=new new ArrayList<String>(); //
Arrays.sort(iArr);
for(int k=0;k<iArr.length;k++) {
list2.add(String.valueOf(iArr[k]));
}
List li2 = new Array List(new HashSet(list2));
I'm unable to get result while trying to Sort Array list. Please correct me.
The TreeSet both sorts the elements and removes the duplicates.
String[] array = { "744101", "744101","744101", "744102","744102","744102","744102","744102","744103","744103"};
List<String> list = new ArrayList<>(new TreeSet<>(Arrays.asList(array)));
list.forEach((element)->{
System.out.println(element);
});
Try this:
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
hash.addAll(list);
list.clear();
list.addAll(hash);
And than sort list if you want.
As Eran mentioned, you current implementation "shuffles" the list due to HashSet implementation being used, as this Set implementation doesn't retain the order. Try using LinkedHashSet instead. As mentioned in javadoc it avoids overheads related to TreeSet.
Code would be something like this
String[] arrayToProcess = { "744101", "744101","744101", "744102","744102","744102","744102","744102","744103","744103"};
//creates array and sorts the list
List<String> sortedList = Arrays.asList(arrayToProcess);
Collections.sort(sortedList);
//removes duplicates the list, while retaining order of sorted list
Set<String> uniqueNumbers = new LinkedHashSet<String>();
uniqueNumbers.addAll(sortedList);
Note the implementation of Set being used is LinkedHashSet. Also this snippet makes two copies of the array so if array size is huge, I wouldn't suggest using it.
I would suggest you look up the implementations of collections in java. Because each of them has their own strengths and weaknesses:
Let's say I have 2 ArrayList of Points:
(0,2)->(0,3)->(0,4)
(0,2)->(0,3)->(0,6)
And I want to obtain a new list : (0,2)->(0,3)
How do I do that?
current solution
Using two foreach loops to compare the two lists, element by element. I think it's a very inefficient way. Are there any other ways?
You can use the List#retainAll(Collection<?> c) method, which:
Retains only the elements in this list that are contained in the specified collection (optional operation). In other words, removes from this list all of its elements that are not contained in the specified collection.
List<Point> first = ...
List<Point> second = ...
first.retainAll(second);
If large lists, add elements of one list to a HashSet and iterate other while keep adding elements to the new list which the HashSet contains
List<Point> list1 = new ArrayList<Point>(Arrays.asList(new Point[]{new Point(0,2), new Point(0,3), new Point(0,4)}));
List<Point> list2 = new ArrayList<Point>(Arrays.asList(new Point[]{new Point(0,2), new Point(0,3), new Point(0,6)}));
Set<Point> setList1 = new HashSet<Point>(list1);
List<Point> intersection = list2.stream().filter( l -> setList1.contains(l)).collect(Collectors.toList());
Time complexity,
Adding to Set = O(n), Iterating list = O(k) time hashset lookup O(1)
~ overall O(n)
I have two big arrays of strings. I want to remove the elements from the first array that do not exist in the second array.
First I create two arrays:
Array to modify:
String[] sarr = fdata.split(System.getProperty("line.separator"));
ArrayList<String> items = new ArrayList(Arrays.asList(sarr));
Filter array:
List<String> filter = new ArrayList<String>();
filter = Arrays.asList(voc.split(System.getProperty("line.separator")))
Then I create Iterator to iterate through the elements of the items array and check if the iterated item exists in filter array, if it does, remove it from items:
Iterator<String> it = items.iterator();
while (it.hasNext()) {
String s = it.next();
if (!filter.contains(s)) {
it.remove();
}
}
items arrays contains 286,568 strings and filter contains 100,000 strings. It appears that the operation takes too much time so I am not doing it efficiently.
Is there a faster way?
Just use different collection types. For the Filter, use HashSet for O(1) (instad of O(n) for ArrayList) search complexity, and for the items, use LinkedList instead of ArrayList - which will be more efficient for the remove operations.
I didn't test this code, but...
String[] sarr = fdata.split(System.getProperty("line.separator"));
LinkedList<String> items = new LinkedList(Arrays.asList(sarr));
Set<String> filter = new HashSet<String>();
filter = new HashSet(Arrays.asList(voc.split(System.getProperty("line.separator"))));
items.retainAll(filter);
When you call collection.contains(element) often for a large collection, you should not use an ArrayList, but rather a HashSet.
Set<String> filter = new HashSet<>();
Collections.addAll(filter, voc.split(System.getProperty("line.separator")));
A HashSet is an optimized data structure for looking up things.
One of the questions I have been given asks:
All the lines should be stored in an object of
type List<Set<Integer>>.
How do you write this in Java, as in how do you initialise this list? I've never seen this before.
Please provide a link to an explanation as i'm not sure what this is called in Java so have no idea about how to learn about it. Thank You.
Its a List of Sets where each Set can hold only Integers.
Set<Integer> singlesSet = new HashSet<>();
singlesSet.add(1);
singlesSet.add(2);
Set<Integer> tensSet = new HashSet<>();
tensSet.add(10);
tensSet.add(20);
List<Set<Integer>> list = new ArrayList<>();
list.add(singlesSet);
list.add(tensSet);
System.out.println(list);
Example of usages of Set and List. Note that elements in a TreeSet are always sorted.
List<Set<Integer>> listofsets = new ArrayList<Set<Integer>>();
Set<Integer> set1 = new TreeSet<Integer>();
set1.add(1);
set1.add(2);
Set<Integer> set2 = new TreeSet<Integer>();
set2.add(6);
set2.add(4);
listofsets.add(set);
// listofsets = {{1,2}, {4,6}}
Like this List<Set<Integer>> yourList = new ArrayList<Set<Integer>>();?
You may want to take a look at https://docs.oracle.com/javase/7/docs/api/java/util/List.html
The short way:
List<Set<Integer>> list = new ArrayList<Set<Integer>>();
Set<Integer> set = new HashSet<Integer>();
list.add(set);
set.add(1);
set.add(2);
....
What is the difference between Set and List?
In Java, the List interface represents an abstract list of things. Any class the implements List (for example, LinkedList) must implement its methods and behave according to its contract.
You can essentially think of it as an array, but keep in mind that arrays are only one kind of list, and that implementations of List do no have to use arrays internally.
The Set also represents a collection of elements, but with no relationship or connection between them. Visually, you can think of a set as a sort of bag of things. You can add and remove things from the bag, but none of the items need to be related.
An Integer, of course, is just an object wrapper around Java's int primitive.
As such, a List<Set<Integer>> object would be similar to a two-dimensional array, only without a defined order in the second dimension.
You would initialize a List<Set<Integer>> as follows:
List<Set<Integer>> myList = new ArrayList<HashSet<Integer>>();
Where ArrayList and HashSet can be any classes that implement List and Set, respectively.
I have 9 different ArrayList and I want to have a list of the top 5.
I'm thinking of sorting those ArrayLists by their sizes.
Is it possible to do that? If so, how can I achieve that?
After a few try i finally got it working, just want to share it with everyone.
it will be better to get the size of the arraylist and add it to the big arraylist
// creates an ArrayList that holds ArrayLists
List allTheLists = new ArrayList();
allTheLists.add(pbaustraliaList.size());
allTheLists.add(pbotherList.size());
allTheLists.add(pbunitedStatesList.size());
allTheLists.add(pbunitedKingdomList.size());
allTheLists.add(pbchinaList.size());
allTheLists.add(pbgermanyList.size());
allTheLists.add(pbindiaList.size());
allTheLists.add(pbjapanList.size());
allTheLists.add(pbsingaporeList.size());
Comparator comparator = Collections.reverseOrder();
Collections.sort(allTheLists,comparator);
//display elements of ArrayList
System.out.println("ArrayList elements after sorting in descending order : ");
for(int i=0; i<allTheLists.size(); i++) {
System.out.println(allTheLists.get(i));
}
What you could do is the following:
// this List of lists will need to contain
// all of the ArrayLists you would like to sort
List<ArrayList> allTheLists;
Collections.sort(allTheLists, new Comparator<ArrayList>(){
public int compare(ArrayList a1, ArrayList a2) {
return a2.size() - a1.size(); // assumes you want biggest to smallest
}
});
This will sort the list of lists by the length of each list. The first element in the sorted list will be the longest list, and the last one will be the shortest list.
Then, you can iterate through the first 5 lists to see what the top 5 were.
Some links for reference:
Sorting tutorial
Collections Javadoc
Comparator Javadoc
Depending on how you have your ArrayLists stored, the code to create a List<ArrayList> would look something like this:
// creates an ArrayList that holds ArrayLists
List<ArrayList> allTheLists = new ArrayList<ArrayList>();
allTheLists.add(yourList1);
allTheLists.add(yourList2);
...
allTheLists.add(yourList9);
you can do like this as well
public static <T> List<List<T>> sort(List<List<T>> list) {
list.sort((xs1, xs2) -> xs1.size() - xs2.size());
return list;
}
The sort method that's available on a List needs a Comparator. That comparator can be created with the Comparator.comparing method, with additional special implementations including for extracting and comparing an int - Comparator.comparingInt.
import static java.util.Comparator.comparingInt;
...
List<List<Integer>> listOfLists = ...
listOfLists.sort(comparingInt(List::size));
List::size will map a List to an int (the size of the list) and use that to create a new Comparator that can be used for our sorting purposes.
If you want largest first
listOfLists.sort(comparingInt(List::size).reversed());
Dump the top 5 (switching over to Java 8 streams):
listOfLists.stream()
.sorted(comparingInt(List::size).reversed())
.limit(5)
.forEachOrdered(System.out::println);