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.
Related
I am looking to prepend the elements of a java.util.ArrayList L1 to another java.util.ArrayList L2 and I cannot find an out of the box way to do it. I do not want to create a third ArrayList and hack around as L2 is the List being used in the view layer. Neither java.util.Collections nor org.apache.commons.collections.CollectionUtils has such a utility method (as far as I can see).
How can I efficiently prepend an ArrayList to another ArrayList, using existing API preferably ? For a java 7 environment.
P.S: addAll appends, I want to prepend.
Use List#addAll(int,Collection):
Inserts all of the elements in the specified collection into this list at the specified position (optional operation). Shifts the element currently at that position (if any) and any subsequent elements to the right (increases their indices). The new elements will appear in this list in the order that they are returned by the specified collection's iterator. The behavior of this operation is undefined if the specified collection is modified while the operation is in progress. (Note that this will occur if the specified collection is this list, and it's nonempty.)
If you use 0 as the index it will prepend the given Collection to the List. For example:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
list1.add("Item #1");
list1.add("Item #2");
list2.add("Item #3");
list2.add("Item #4");
System.out.println("List #1: " + list1);
System.out.println("List #2: " + list2);
list2.addAll(0, list1);
System.out.println("Combined List: " + list2);
}
}
Output:
List #1: [Item #1, Item #2]
List #2: [Item #3, Item #4]
Combined List: [Item #1, Item #2, Item #3, Item #4]
subList gives you a view into a list. If you make a view at the very start of the list, addAll will do the right thing.
ArrayList<String> list = new ArrayList<String>(Arrays.asList("extant1", "extant2"));
ArrayList<String> prefix = new ArrayList<String>(Arrays.asList("prefix1", "prefix2"));
list.subList(0, 0).addAll(prefix);
list
// => list ==> [prefix1, prefix2, extant1, extant2]
Simply You can do this way:
List<String> l1 = new ArrayList<>();
List<String> l2 = new ArrayList<>();
l1.add("a");
l1.add("b");
l2.add("c");
l2.add("d");
l1.addAll(l2);
System.out.println(l1); // if you want result in list 1
l2.clear();
l2.addAll(l1);
System.out.println(l2); // if you want result in list 2
I don't see any particular inbuilt function that can do this thing. Here is the trick I am following to solve this.
If L1 is {1,2} and L2 is {3,4} then
Reverse the list L1 (It will become {2,1} )
Iterate the list L2 from back and add the
elements to L1. (You can also reverse L2 and do addAll on L1. If you
are ok with modifying L2, do it) (L1 will become {2,1,4,3} )
Reverse the list L1 (L1 will become {3,4,1,2} )
Total Time Complexity : O(m+n) where m is size of L1 and n is size of L2
List<Integer> li1 = new ArrayList<>();
li1.add(1);
li1.add(2);
List<Integer> li2 = new ArrayList<>();
li2.add(3);
li2.add(4);
Collections.reverse(li1);
ListIterator<Integer> listIterator = li2.listIterator(li2.size());
while (listIterator.hasPrevious())
{
Integer previous = listIterator.previous();
li1.add(previous);
}
Collections.reverse(li1);
System.out.println(li1);
If you don't want to use Collections.addAll​(int index, Collection c)
public static void main(String[] args) {
List<String> orginalList = new ArrayList<>(Arrays.asList( "E","F","G","H"));
System.out.println(orginalList);
Collections.reverse(orginalList);
List<String> newList = new ArrayList<>(Arrays.asList( "A","B","C","D"));
System.out.println(newList);
Collections.reverse(newList);
orginalList.addAll(newList);
Collections.reverse(orginalList);
System.out.println(orginalList);
}
Checking docs.oracle showed me one function. ArrayList.add(int index, E element) This helps, because you can place the items of the ArrayList at the beginning of the array, for example:
ArrayList <Integer> L1 = {2, 3, 5, 7} /*Imaginary declaration*/, L2 = {500, 600};
for(int i=0; i<L1.size(); i--) L2.add(0, L1.get(i));
But this will leave L2 with {7, 5, 3, 2, 500, 600} because each element added at index [0] will push the next ones forward. Instead, do it the opposite way:
for(int i=L1.size()-1; i>=0; i++) L2.add(0, L1.get(i));
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).
As per some condition i add some values(it may single or multiple values) in my Arraylist.
in common method:
List<Object> listsALL.....
listsALL.add(sItems2);
value will return to calling method.
i can access values below way
sItems100.add(String.valueOf(listsALL.get(3)));
output like
sItems100---------------- [[Item 5, Item 7]]
While fetching the value from sItems100 and add into nested list, i'm getting below output
[[Item 1, Item 2, Item 6], [[Item 5, Item 7]]]
but i expect like
[[Item 1, Item 2, Item 6], [Item 5, Item 7]]
How to resolve this, any one can help in this?
Do you want something like this?
List<Object> listsALL = new ArrayList<Object>();
List<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
list1.add(2);
list1.add(6);
List<Integer> list2 = new ArrayList<Integer>();
list2.add(5);
list2.add(7);
listAll.add(list1);
listAll.add(list2);
It is not a great idea to keep a List of generic Objects of different types (e.g. List in your case), and to insert both an singular Object and a List in this initial list.
If it is possible, try using a
List<List<Object>>
instead. Don't forget that List is an interface, implemented below by ArrayList class.
ArrayList<ArrayList<String>> aList = new ArrayList<ArrayList<String>>();
ArrayList<String> firstElement = new ArrayList<String>();
firstElement.add("Object1");
ArrayList<String> secondElement = new ArrayList<String>();
secondElement.add("Object2");
secondElement.add("Object3");
aList.add(firstElement);
aList.add(secondElement);
System.out.println(aList.get(0).get(0));
System.out.println(aList.get(1).get(0));
System.out.println(aList.get(1).get(1));
Here you have two similar Lists in the initial aList, one with only one element, one with two elements.
If you want to use both an Object and a List inside your initial list, you might want to check how to use instanceof operator and casting in Java.
if(aList.get(1) instanceof ArrayList){
System.out.println("True");
}
else {
System.out.println("False");
}
Here is the full example of using instanceof:
ArrayList<Object> aList = new ArrayList<Object>();
String firstElement = "Object1";
ArrayList<String> secondElement = new ArrayList<String>();
secondElement.add("Object2");
secondElement.add("Object3");
aList.add(firstElement);
aList.add(secondElement);
for (int i = 0; i < aList.size(); i++){
if (aList.get(i) instanceof String ){
System.out.println( (String) aList.get(i) );
}
if (aList.get(i) instanceof ArrayList){
System.out.println( ((ArrayList<String>)aList.get(i)).get(0) );
}
}
So the initial aList holds two types of Objects in this case, String and ArrayList. When iterating the list, you use instanceof operator to see what type of Object it is, and cast it accordingly.
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);
I have two ArrayList objects with three integers each. I want to find a way to return the common elements of the two lists. Has anybody an idea how I can achieve this?
Use Collection#retainAll().
listA.retainAll(listB);
// listA now contains only the elements which are also contained in listB.
If you want to avoid that changes are being affected in listA, then you need to create a new one.
List<Integer> common = new ArrayList<Integer>(listA);
common.retainAll(listB);
// common now contains only the elements which are contained in listA and listB.
You can use set intersection operations with your ArrayList objects.
Something like this:
List<Integer> l1 = new ArrayList<Integer>();
l1.add(1);
l1.add(2);
l1.add(3);
List<Integer> l2= new ArrayList<Integer>();
l2.add(4);
l2.add(2);
l2.add(3);
System.out.println("l1 == "+l1);
System.out.println("l2 == "+l2);
List<Integer> l3 = new ArrayList<Integer>(l2);
l3.retainAll(l1);
System.out.println("l3 == "+l3);
Now, l3 should have only common elements between l1 and l2.
CONSOLE OUTPUT
l1 == [1, 2, 3]
l2 == [4, 2, 3]
l3 == [2, 3]
Why reinvent the wheel? Use Commons Collections:
CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)
Using Java 8's Stream.filter() method in combination with List.contains():
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
/* ... */
List<Integer> list1 = asList(1, 2, 3, 4, 5);
List<Integer> list2 = asList(1, 3, 5, 7, 9);
List<Integer> common = list1.stream().filter(list2::contains).collect(toList());
consider two list L1 ans L2
Using Java8 we can easily find it out
L1.stream().filter(L2::contains).collect(Collectors.toList())
You can get the common elements between two lists using the method
"retainAll". This method will remove all unmatched elements from the list to
which it applies.
Ex.: list.retainAll(list1);
In this case from the list, all the elements which are not in list1 will be
removed and only those will be remaining which are common between list and
list1.
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(13);
list.add(12);
list.add(11);
List<Integer> list1 = new ArrayList<>();
list1.add(10);
list1.add(113);
list1.add(112);
list1.add(111);
//before retainAll
System.out.println(list);
System.out.println(list1);
//applying retainAll on list
list.retainAll(list1);
//After retainAll
System.out.println("list::"+list);
System.out.println("list1::"+list1);
Output:
[10, 13, 12, 11]
[10, 113, 112, 111]
list::[10]
list1::[10, 113, 112, 111]
NOTE: After retainAll applied on the list, the list contains common element between
list and list1.
List<String> lista =new ArrayList<String>();
List<String> listb =new ArrayList<String>();
lista.add("Isabella");
lista.add("Angelina");
lista.add("Pille");
lista.add("Hazem");
listb.add("Isabella");
listb.add("Angelina");
listb.add("Bianca");
// Create an aplusb list which will contain both list (list1 and list2) in which common element will occur twice
List<String> listapluslistb =new ArrayList<String>(lista);
listapluslistb.addAll(listb);
// Create an aunionb set which will contain both list (list1 and list2) in which common element will occur once
Set<String> listaunionlistb =new HashSet<String>(lista);
listaunionlistb.addAll(listb);
for(String s:listaunionlistb)
{
listapluslistb.remove(s);
}
System.out.println(listapluslistb);
public <T> List<T> getIntersectOfCollections(Collection<T> first, Collection<T> second) {
return first.stream()
.filter(second::contains)
.collect(Collectors.toList());
}
// Create two collections:
LinkedList<String> listA = new LinkedList<String>();
ArrayList<String> listB = new ArrayList<String>();
// Add some elements to listA:
listA.add("A");
listA.add("B");
listA.add("C");
listA.add("D");
// Add some elements to listB:
listB.add("A");
listB.add("B");
listB.add("C");
// use
List<String> common = new ArrayList<String>(listA);
// use common.retainAll
common.retainAll(listB);
System.out.println("The common collection is : " + common);
In case you want to do it yourself..
List<Integer> commons = new ArrayList<Integer>();
for (Integer igr : group1) {
if (group2.contains(igr)) {
commons.add(igr);
}
}
System.out.println("Common elements are :: -");
for (Integer igr : commons) {
System.out.println(" "+igr);
}
Some of the answers above are similar but not the same so posting it as a new answer.
Solution:
1. Use HashSet to hold elements which need to be removed
2. Add all elements of list1 to HashSet
3. iterate list2 and remove elements from a HashSet which are present in list2 ==> which are present in both list1 and list2
4. Now iterate over HashSet and remove elements from list1(since we have added all elements of list1 to set), finally, list1 has all common elements
Note: We can add all elements of list2 and in a 3rd iteration, we should remove elements from list2.
Time complexity: O(n)
Space Complexity: O(n)
Code:
import com.sun.tools.javac.util.Assert;
import org.apache.commons.collections4.CollectionUtils;
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
List<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(3);
list2.add(5);
list2.add(7);
Set<Integer> toBeRemoveFromList1 = new HashSet<>(list1);
System.out.println("list1:" + list1);
System.out.println("list2:" + list2);
for (Integer n : list2) {
if (toBeRemoveFromList1.contains(n)) {
toBeRemoveFromList1.remove(n);
}
}
System.out.println("toBeRemoveFromList1:" + toBeRemoveFromList1);
for (Integer n : toBeRemoveFromList1) {
list1.remove(n);
}
System.out.println("list1:" + list1);
System.out.println("collectionUtils:" + CollectionUtils.intersection(list1, list2));
Assert.check(CollectionUtils.intersection(list1, list2).containsAll(list1));
output:
list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]
public static <T> List<T> getCommonElements(
java.util.Collection<T> a,
java.util.Collection<T> b
) {
if(a==null && b==null) return new ArrayList<>();
if(a!=null && a.size()==0) return new ArrayList<>(b);
if(b!=null && b.size()==0) return new ArrayList<>(a);
Set<T> set= a instanceof HashSet?(HashSet<T>)a:new HashSet<>(a);
return b.stream().filter(set::contains).collect(Collectors.toList());
}
For better time performance, please use HashSet (O(1) look up) instead of List(O(n) look ups)
Time complexity- O(b)
Space Complexity- O(a)
Below code
Remove common elements in the list
List<String> result = list1.stream().filter(item-> !list2.contains(item)).collect(Collectors.toList());
Retrieve common elements
List<String> result = list1.stream()
.distinct()
.filter(list::contains)
.collect(Collectors.toList());
The question talks about three items and many of the suggestions suggest using retainAll. I think it must be stated that as the size of the lists grown retainAll seems to become more inefficient.
In my tests I found that converting to Sets and looping is around 60 times faster than using retainAll for Lists with 1000s of items
List<Integer> common(List<Integer> biggerList, List<Integer> smallerList) {
Set<Integer> set1 = new HashSet<>(biggerList);
List<Integer> result = new ArrayList<>(smallerList.size());
for (Integer i : smallerList) {
if (set1.contains(i)) {
result.add(i);
}
}
return result;
}
Using Java 8 below solution
list1.stream()
.filter(list2::contains)
.collect(Collectors
.toList()));