Get order of list by value - java

I have an order of list with different values:
List<Double> values = new LinkedList<Double>();
values.add(0.1);
values.add(0.8);
values.add(0.3);
What is the fastest way to get a list with indexes depending on the order of values of the given list, in this case {1, 3, 2} because 0.1 is the smallest, 0.2 the second smallest and 0.8 the third smallest?

A way to get this index list, using only jdk5
List<Float> positions = new ArrayList<Float>();
List<Integer> indexes = new ArrayList<Integer>();
positions.add(0.1f);
positions.add(0.8f);
positions.add(0.3f);
// copy float elements to another List, so to keep the order
List<Float> sortedPositions = new ArrayList<Float>();
Collections.copy(sortedPositions, positions);
Collections.sort(sortedPositions);
for (Float position : positions) {
indexes.add(sortedPositions.indexOf(position));
}
for (Integer index : indexes) {
System.out.print(index + ",");
}
// prints 1,3,2,

If all the values are uniques, one way is to use a TreeMap and then get back the corresponding indexes calling values().
TreeMap<Double, Integer> map = new TreeMap<>();
int index = 0;
for(Double d : values){
map.put(d, ++index);
}
System.out.println(map.values()); //[1, 3, 2]
This approach runs in O(nlogn) (but uses extra memory space).
If the values are not unique, you could use a TreeMap<Double, List<Integer>> and then flatmap the Collection<List<Integer>>

You have to sort the list so that it will be sorted in the natural order before using is:
Collections.sort(values);

Related

Binding 2 arraylists android

At first Sorry if title doesn't really explain the problem as it should be.
I have 2 ArrayList in my android (java) code
as example lets say the first is made of strings and the second is made of integers.
ArrayLis<String> strings = new ArrayList<String>();
strings.add("s1");
strings.add("s2");
strings.add("s1");
strings.add("s3");
strings.add("s4");
strings.add("s1");
strings.add("s2");
ArrayList<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
ints.add(5);
ints.add(3);
ints.add(4);
ints.add(3);
ints.add(2);
Taking this example, lets say each value in array list strings correspond to a value of array ints but the int value might change
I want to remove the repetition in the string array, I used LinkedHashSet to do so:
LinkedHashSet<String>hashset = new LinkedHashSet<>(strings);
strings = new ArrayList<> hashset;
The issue now is i removed the duplicate string entries but i also removed the link between each string and its int value.
how can I get the new "ints" array using the minimal int value for the string for example for s1 that has 1, 5 and 3 as bound values get the 1 value as so:
strings = ["s1", "s2", "s3", "s4"];
ints = [1, 2, ,3, 4];
I thought of using maps. but is it the best way to do it? (map the string to the int and whenever a repetition occures check int if smaller and replace map value)
I'd iterate over the string list and convert it to a linked map for the string value to the minimal int. Once that's done, if you really want to, you could re-create the two lists:
Map<String, Integer> map = new LinkedHashMap<>();
for (int index = 0; index < strings.size(); ++i) {
final int i = index;
map.compute(
strings.get(i), (k, v) -> v == null ? ints.get(i) : Math.min(v, ints.get(i)));
}
// If you want two lists again:
strings = new ArrayList<>(map.keySet());
ints = new ArrayList<>(map.values());

Arraylist Comparison using one loop

It has been a long since something came to my mind while starting to code and using lists or array lists. When comparing values of one array to every other elements in another array, I used to do it in two for loops since it was the easiest way to do that.but recently I came to know that it increases much time complexity, I thought about another solution.can anyone help me in solving this case using any algorithm. I am using java.but solution in any language would be fine. just the algorithm to do that is needed. Thanks in advance.
This is what i am doing:
a1 = [1,2,3,4,5]
b1 = [9,5,4,3,8,3,7]
I want to check how much time an element in a1 occurs in b1
So what i am doing is:
count = 0;
for(int i = 0;i <a1.length;i++)
{
for(j=0;j<b1.length;j++)
{
if (a1[i] == b1[j])
{
count = count+1;
}
}
}
print("count is" count);
Theres no need of loop to obtain what you want
ArrayList<Integer> l1 = new ArrayList<Integer>();
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.add(5);
ArrayList<Integer> l2 = new ArrayList<Integer>();
l2.add(9);
l2.add(5);
l2.add(4);
l2.add(3);
l2.add(8);
l2.add(3);
l2.add(7);
ArrayList<Integer> lFiltered = new ArrayList<Integer>(l2);
lFiltered.removeAll(l1);
int Times = l2.size() - lFiltered.size();
System.out.println("number of migrants : " + Times);
Suffice it to to generate from l2 a list without elements and l1 and to count elements which have been removed
Use hashing, e.g. using a Set or Map
If you want to compare the objects as a whole:
properly implement equals and hashcode for your class (if not implemented already)
put all the elements of list A into a Set, then see which elements from list B are in that Set
If you just want to compare objects by some attribute:
define a method that maps the objects to that attribute (or combination of attriutes, e.g. as a List)
create a Map<KeyAttributeType, List<YourClass>> and for each element from list A, add the element to that Map: map.get(getKey(x)).add(x)
for each element from list B, calculate the value of the key function and get the elements it "matches" from the map: matches = map.get(getKey(y))
Given your code, your case seems to be a bit different, though. You have lists or arrays of numbers, so no additional hashing is necessary, and you do not just want to see which items "match", but count all combinations of matching items. For this, you could create a Map<Integer, Long> to count how often each element of the first list appears, and then get the sum of those counts for the elements from the second list.
int[] a1 = {1,2,3,4,5};
int[] b1 = {9,5,4,3,8,3,7};
Map<Integer, Long> counts = IntStream.of(b1).boxed()
.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
System.out.println(counts); // {3=2, 4=1, 5=1, 7=1, 8=1, 9=1}
long total = IntStream.of(a1).mapToLong(x -> counts.getOrDefault(x, 0L)).sum();
System.out.println(total); // 4
Of course, instead of using the Stream API you can just as well use regular loops.
Use ArrayLists.
To compare the content of both arrays:
ArrayList<String> listOne = new ArrayList<>(Arrays.asList(yourArray1);
ArrayList<String> listTwo = new ArrayList<>(Arrays.asList(yourArray);
listOne.retainAll(listTwo);
System.out.println(listOne)
To find missing elements:
listTwo.removeAll(listOne);
System.out.println(listTwo);
To enumerate the Common elements:
//Time complexity is O(n^2)
int count =0;
for (String element : listOne){
for (String element2: listTwo){
if (element.equalsIgnoreCase(elemnt2){
count += 1;
}
}
}

Find duplicated items in a list with limited heap

There is an N + 1 length, read-only list of numbers between 1 and N.
There is a duplicate item in the list, but there may be more.
For Example N=3, items of the list [1,3,1,3]
I need an algorithm that prints the duplicated items.(doesn't matter how many times an item is in it)
Based on the example above, the result is 1,3
I need a solution in java that works with limeted heap(can run with many items in short time)
I've tried to create a new HashSet and add items from the list to the set, and if it already contains the item, I've saved it to an ArrayList.
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(1);
list.add(2);
list.add(5);
Set<Integer> set = new HashSet();
List<Integer> duplicatedList = new ArrayList<>();
for (Integer item : list) {
if(set.contains(item)) {
duplicatedList.add(item);
}
set.add(item);
}
System.out.println(duplicatedList +" "+ list);
It works, but i think this is not too effective. Is there a more efficient solution, for this problem?
If you want limited heap usage, remove non-duplicates from the original list, instead of creating a new list. Also use BitSet to track already seen numbers.
List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,1,2,5));
int N = list.size() - 1;
BitSet present = new BitSet(N);
for (Iterator<Integer> iter = list.iterator(); iter.hasNext(); ) {
int value = iter.next();
if (! present.get(value)) {
present.set(value);
iter.remove();
}
}
System.out.println(list);
Output
[1, 2]
If original list is read-only, build a new list like in question.
List<Integer> list = Arrays.asList(1,2,3,4,1,2,5);
BitSet present = new BitSet();
List<Integer> duplicatedList = new ArrayList<>();
for (Integer item : list) {
if (present.get(item))
duplicatedList.add(item);
else
present.set(item);
}
System.out.println(duplicatedList +" "+ list);
Output
[1, 2] [1, 2, 3, 4, 1, 2, 5]
The main improvement is the use of BitSet instead of Set<Integer>, relying on the fact that the range of numbers is limited to be between 1 and N, so the space used is lot less (except in extreme conditions).

Substituting in arraylists

I have an hash map, which maps integers to array of ArrayLists. For example, my data structure is the following:
7->((7,5,**4,3,1**),(7,6,4,3,1))
4->((4,2,1),(4,3,1))
Here, 7 is key, and arraylist e.g is (7,5,4,3,1), the array of arraylist in turn is ((7,5,4,3,1),(7,6,4,3,1))
4 is key, and arraylist e.g. is (4,2,1), the array of arraylist in turn is ((4,2,1),(4,3,1))
I wish to substitute the key values (in any given arraylist) and the values following it to create other arraylists, one example of this is given below:
7->((7,5,**4,2,1**),(7,6,4,2,1),(7,5,4,3,1),(7,6,4,3,1))
the thing I am not getting is how to obtain this substitution....to create bigger arraylists
the thing I am not getting is how to obtain this substitution....to create bigger arraylists..i know the datastructure..but want to create arraylists by substitution as given in subsequent example
Is there someway in java programming by which I may achieve this?
I am a novice at Java programming...I thought long about this but could not move it...can someone please help
HashMap<Integer,ArrayList<ArrayList<Integer>>> map;
map = new HashMap<Integer,ArrayList<ArrayList<Integer>>>();
EDIT: I've used 2 lines so that my answer could be more readable.
What actually do you want?
Is bellow code helpful?
Map<Integer, List<List<Integer>>> mapData = new HashMap<Integer, List<List<Integer>>>();
public void fillData(List<List<Integer>> lists)
{
// provide any kind of list of list
// e.g lists = {2,3,5,3}, {4,5,3,2}, {2,4,3}, {6,3,4}
for(List<Integer> list : lists)
{
int mapKey = list.get(0);
if(mapData.get(mapKey) == null)
{
// list of list will be null in first occurence of key(first element of list).
// create list of list and put tat in map.
List<List<Integer>> tempListOfList = new ArrayList<List<Integer>>();
tempListOfList.add(list);
mapData.put(mapKey, tempListOfList);
}
else
{
// from second occurence of same key.
// put list in the list of list of that key.
List<List<Integer>> listOfListInMap = mapData.get(mapKey);
listOfListInMap.add(list);
}
}
}
public List<List<Integer>> getListsByKey(int key)
{
// get list of list by mapKey
return mapData.get(key);
}
HashMap<Integer, ArrayList<ArrayList<Integer>>>.
below should do it:
Map<Integer, ArrayList <ArrayList<Integer>>> map = new hashMap<>();
Consider using a List of Lists and store this as part of a Map data structure. One possible way would be as follows:
Map<Integer,List<List<Integer>>> map = new HashMap<Integer, List<List<Integer>>>();
//How to add
List<List<Integer>> list = map.get(your_key);
if(list == null){ //This should be for the first time you're accessing the map with the key
list = new ArrayList<List<Integer>>();
}
//Create a inner list which will store the list of numbers
ArrayList<Integer> innerList = new ArrayList<Integer>();
innerList.add(integer_values);
//Add inner list to the list of lists
list.add(innerList);
//Finally put the list of list into the map with the key
map.put(your_key, list);
Edit: Assuming you know index of the list where you want to add new elements:
//Adding numbers to the inner list - assume you know the index
List<List<Integer>> list = map.get(key);
if(list == null || list.size() >= index){ //There's no list against the key or the size of the list is less then the index requested
return;
}
//Add new elements to the inner list
List<Integer> innerList = list.get(index);
innerList.add(your_new_int_values);
//Add inner list to the list of lists
list.add(innerList);
//Finally put the list of list into the map with the key
map.put(key, list);
You want to map integers to a list of lists of integers. This can be declared as:
Map<Integer, List<List<Integer>>> map = new HashMap<List<List<Integer>>>();
You can then put instances of ArrayList<List<Integer>> (or any other class that implements List) and for each such list of lists, you can add instances of ArrayList<Integer>.
You can then use the List.subList() method to put selected sublists into other entries in the map.
Say you have a list containing the two lists (7,5,4,3,1) and (7,6,4,3,1) stored under 7 and you want to construct the list of lists that should be stored under the key 4. You can do this:
List<List<Integer>> sevens = map.get(7);
List<List<Integer>> fours = new ArrayList<List<Integer>>();
for (List<Integer> aSevenList : sevens) {
int index = aSevenList.indexOf(4);
if (index >= 0) {
fours.add(aSevenList.subList(index, aSevenList.size()));
}
}
map.put(4, fours);
If you want to substitute one list as part of another, the following code fragment shows how that might be done:
int[] vals = { 7, 6, 5, 4, 3, 2, 1 };
List<Integer> list = new ArrayList<Integer>();
for (int val : vals) list.add(val);
List<Integer> sub = new ArrayList<Integer>();
sub.add(40);
sub.add(30);
sub.add(20);
System.out.println("Original list: " + list);
List<Integer> slice = list.subList(3, vals.length - 1);
slice.clear();
slice.addAll(sub);
System.out.println("Modified list: " + list);
This will generate the following output:
Original list: [7, 6, 5, 4, 3, 2, 1]
Modified list: [7, 6, 5, 40, 30, 20, 1]
Note that changes to a sublist are propagated to the original list.

Subtracting one arrayList from another arrayList

I have two arrayLists and I am trying to "subtract" one arrayList from another. For example, if I have one arrayList [1,2,3] and I am trying to subtract [0, 2, 4] the resulting arrayList should be [1,3].
List<Integer> a = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Integer> b = Arrays.asList(0, 2, 4);
subtract(a,b) // should return [1,3]
Here is my code.
//returns a new IntSet after subtracting a from b
// .minus().toString()
ArrayList<Integer> minusArray = new ArrayList<Integer>();
minusArray.addAll(array1);
for(int i =0; i< minusArray.size(); i++){
for(int j = 0; j < array2.size(); j++){
if(minusArray.get(i).equals(array2.get(j))){
minusArray.remove(i);
if(i == 0){
;
}
else if(j == 0){
;
}
else{
i = 0;
j = 0;
}
}
else{}
}
}
return minusArray;
My code works in some cases, like if arrayList1 = [4,6] and arrayList2 = [6] it will will give me a result of [4]. But if I try something like [1,2,4] and [0,4,8]
I get this exception:
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at IntSet.minus(IntSet.java:119)
at IntSetDriver.main(IntSetDriver.java:62)
Here is the code I have come up with. I have done test runs through it and to me I think it should work. The user inputs these arrayLists and they are presorted, I also do not know Hash or big-O.
ArrayList<Integer> minusArray = new ArrayList<Integer>();
minusArray.addAll(array1);
for(int i =0; i< minusArray.size(); i++){
for(int j = 0; j < array2.size(); j++){
if(minusArray.get(i).equals(array2.get(j))){
minusArray.remove(i);
}
else{}
}
}
return minusArray;
Is there some reason you can't simply use List.removeAll(List)?
List<Integer> one = new ArrayList<Integer>();
one.add(1);
one.add(2);
one.add(3);
List<Integer> two = new ArrayList<Integer>();
two.add(0);
two.add(2);
two.add(4);
one.removeAll(two);
System.out.println(one);
result: "[1, 3]"
Try to use subtract method of org.apache.commons.collections.CollectionUtils class.
Returns a new Collection containing a - b. The cardinality of each element e in the returned Collection will be the cardinality of e in a minus the cardinality of e in b, or zero, whichever is greater.
CollectionUtils.subtract(java.util.Collection a, java.util.Collection b)
From Apache Commons Collections
Java 8
You can also use streams:
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(1, 2, 4, 5);
List<Integer> diff = list1.stream()
.filter(e -> !list2.contains(e))
.collect (Collectors.toList()); // (3)
This answer does not manipulate the original list. If intention is to modify the original list then we can use remove. Also we can use forEach (default method in Iterator) or stream with filter.
Using ListUtils
Another option is to use ListUtils if we are using Apache common:
ListUtils.subtract(list, list2)
This subtracts all elements in the second list from the first list, placing the results in a new list. This differs from List.removeAll(Collection) in that cardinality is respected; if list1 contains two occurrences of null and list2 only contains one occurrence, then the returned list will still contain one occurrence.
Traversing the minusArray using an index is one way to do this, but I suggest you make use of the contains(Object) method, which will allow you then to use remove(Object) for the particular element of array2.
Of course, there's always the removeAll(Collection) which does pretty much everything you need...
You can use org.apache.commons.collections.ListUtils and make all that you want in only one line =)
List resultList = ListUtils.subtract(list, list2);
Your problem is that in your minusArray.remove(...) call you may shrink the size of the minusArray. To fix this, start at array.size() - 1 and count backwards to 0
Check that - even that won't fix it. You need to reverse the order of your loops
I'm guessing you get the range problem because you've eliminated one of the elements which changes what the inner loop is looking for (I know this problem occurs when dealing with normal Lists and Collections).
What I've had to do in the past to work around this, is to create a list of items that need to be removed (that is ones that are found in the original list). Iterate through that new list and directly eliminate the original list's elements without having to have an iterator moving through it.
Try this answer if removeAll() is not what you want. e.g. if you are interested in something like Calculating difference of two lists with duplicates
subtract(a,b)
b.forEach((i)->a.remove(i));
a now contains
[1, 3]
This follows the suggestion of Guava implementors on how to implement subtract
"create an ArrayList containing a and then call remove on it for each element in b."
Which behaves like this implementation used in Apache commons
Difference to removeAll()
[1,2,2,3].removeAll([1,2,3]) //is empty
[1,2,3].forEach((i)->[1,2,2,3].remove(i)); //a is [2]
My parameterized solution would be like:
<T> ArrayList<T> subtract(ArrayList<T> alpha, ArrayList<T> beta) {
ArrayList<T> gamma = new ArrayList<T>();
alpha.forEach(n -> {if (!beta.contains(n)) gamma.add(n); });
return gamma;
}

Categories