I'm facing a problem when operating on an ArrayList of ArrayList in Java. I have this thing in my code-
ArrayList<ArrayList<Integer>> L1 = new ArrayList<ArrayList<Integer>>();
Problem is, I have no idea as to how I should operate on this (addition, removal, traversal etc.). I wish to create an adjacency list (for implementing simple, undirected graphs), and my instructor suggests that I should create an ArrayList of ArrayList. I know I can do the following to add new element-
L1.add(//Something I want to add);
But this throws up an error in the current case for obvious reasons.
An ArrayList of an ArrayList, just think that the outer object is an ArrayList and you are done.
ArrayList<ArrayList<Integer>> list2d = new ArrayList<ArrayList<Integer>>();
// add an element to the list
list2d.add(new ArrayList<Integer>());
// retrieve a list
ArrayList<Integer> list1d = list2d.get(0);
// add an integer
list2d.get(0).add(123);
By the way, an adjacency list is just a list of edges, there's no need to store them for each vertex, especially if the graph is undirected. A list of Edge would be enough:
class Edge {
Vertex v1, v2;
}
ArrayList<Edge> adjacencyList;
If you want to store them on a per vertex basis then you could avoid using a list of lists by encapsulating the edges inside the vertex class itself but this will require twice the edges:
class Vertex {
int value;
ArrayList<Vertex> adjacency;
}
but which one is best depends on what kind of operation you need to perform on the graph. For a small graph there is no practical difference.
Another possible implementation, if you just need to know if two vertex are connected:
class Edge {
public final int v1, v2;
public boolean equals(Object o) { return o != null && o instanceof Edge && o.hashCode() == hashCode(); }
public int hashCode() { return v1 ^ v2; } // simple hash code, could be more sophisticated
}
Set<Edge> adjacencyList = new HashSet<Edge>();
Try L1.get(i).add(whatever);, and of course first check whether L1.get(i) exists, otherwise add that inner list first.
It's something like this:
List<List<Integer>> L1 = new ArrayList<List<Integer>>(); //better use interfaces
List<Integer> first = null;
if( L1.size() > 0) {
first = L1.get(0); //first element
}
else {
first = new ArrayList<Integer>();
L1.add(first);
}
first.add(4711); //or whatever you like to add
List<List<Integer>> L1 = new ArrayList<ArrayList<Integer>>();
List<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
//add list to the list
L1.add(list1);
iterate over the list of lists
for( List<Integer> list: L1 ){
for(Integer i:list){
System.out.println(i);
}
}
You can only add objects of type ArrayList to L1. So you could do this:
ArrayList<ArrayList<Integer>> firstList = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> secondList = new ArrayList<Integer>();
secondList.add(0);
firstList.add(secondList);
L1.add(new ArrayList<Integer>());
will create a new List within the first list. Then you can
L1.get(0).add(5)
To add a new element to the outer array:
ArrayList<Integer> inner = new ArrayList<Integer>();
L1.add(inner);
Then to add element to the inner array:
int exampleInt = 10;
ArrayList<Integer> inner = L1.get(0);
inner.add(exampleInt);
To traverse all elements in all arrays:
for (ArrayList<Integer> inner : L1)
{
for (Integer element : inner)
{
System.out.println(element);
}
}
Related
I have been struggling on this problem for two days. This problem comes from some problem I am doing. Basically, when I use
List<List<Integer>> temp = new ArrayList<>(result);
to create a new ArrayList copy of result, the result will change when I try to change temp within an advanced for loop. For example,
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
List<List<Integer>> temp = new ArrayList<>(result);
int j = 0;
for (List<Integer> list: temp) {
list.add(x[j]);
j ++;
}
I did nothing to the result inside the loop but the result ends up with [[1]], which is the same as temp.
Why is this happening? Thanks a lot.
Update: thank everybody for answering my question. I learn the shallow copy was the reason. However, I still run into a similar problem. The result is updated while I try to change the temp in the following code:
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
List<List<Integer>> temp = new ArrayList<>();
for (List<Integer> list: result) {
list.add(10000);
temp.add(new ArrayList(list));
}
I do not know why the result turns out to be [[10000]] as well as the temp. Is there anything wrong with the add method like temp.add(new ArrayList(list))?
This is happening because the List<List<Integer>> temp = new ArrayList<>(result); statement copies only the top-level list. It will be the new list that contains references to the original items (aka sublists) from the original result.
You can fix this with a deep copy:
List<List<Integer>> temp = new ArrayList<>(); // empty list
for (List<Integer> sublist : result) {
temp.add(new ArrayList<Integer>(result)); // copying a sublist and adding that
}
temp = new ArrayList<>(result) only does a shallow copy of result, i.e. it copies the "outer" list, but not its elements.
temp.get(0) == result.get(0) - and I don't mean equals - they are exactly the same instance.
As such, anything you add to temp.get(0) will also appear in result.get(0).
This is not surprising because you have only one list to iterate upon. If you add a second list you will see a second digit coming in.
int[] x = new int[]{1,2,3,4,5};
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList());
result.add(new ArrayList());
List<List<Integer>> temp = new ArrayList<>(result);
for (Integer xx: x) {
result.add(new ArrayList(xx));
}
System.out.println(result.toString());
If you try this code it will display you:
[[1],[2]]
I have a 2d ArrayList which stores objects, i want to check if a certain object exists in any of of the rows, and if not add a new row, and search that object in future checks. eg.
ArrayList<List<Object>> list = new ArrayList<>();
for(List<Object> o : list) {
if(!o.contains(object){
ArrayList<Object> newList = new ArrayList<>();
newList.add(object);
list.add(newList);
}
}
This gives me a 'ConcurrentModificationException' but I can't find another way to do it.
Thanks in advance.
list.add(newList); this line should be outside your for loop. You are trying to modify your list while iterating on it. Just keep adding elements to newList in the for loop. Add the line list.add(newList); after the for loop.
You cannot change a List while you are iterating over its items.
What you can do is:
ArrayList<List<Object>> list = new ArrayList<>(); // in practice this would not be an empty list, but it would, as in your example, contain all items
ArrayList<List<Object>> newRows = new ArrayList<>();
for(List<Object> o : list) {
if(!o.contains(object){
ArrayList<Object> newList = new ArrayList<>();
newList.add(object);
newRows.add(newList);
}
}
list.addAll(newRows);
You have to replace:
for(List o : list) {
with:
for(int i = 0; i < list.size(); i++) {
List o = list.get(i);
Just be careful when you do this to handle how you modify the list. In this case there should be no problem.
I have List of ArrayList Elements, see below.
List<List<String>> x = new ArrayList<List<String>>();
it contains some array list elements.
eg.
x.get(0)->[1,2,3,4],
x.get(1)->([5,6,7,8],
x.get(2)->[9,10,11,12],
x.get(3)->[13,14,15,16]
i want to access element 3 from x.get(0) or element 7 from x.get(1) how to call that??
Each element of your list is a list and has the same interface that provides List<T> methods, e.g.
T get(int index)
boolean isEmpty()
void add(T element)
etc.
You can access element from the inner list by index
List<List<String>> x = new ArrayList<List<String>>();
// ... some data initialised
String element_0_3 = x.get(0).get(3);
Be aware that each List<String> element needs to have been created before accessing it. For instance, in order to add a new String at the [0,0] coordinates:
List<List<String>> x = new ArrayList<List<String>>();
List<String> x0 = new ArrayList<>();
x0.add("foo"); // add "foo" as the first string element
x.add(x0); // add x0 as the first List<String> element
You can also read values with an enhanced for loop, without using the indexes:
List<List<String>> x = new ArrayList<List<String>>();
//...
for (List<String> ls : x) { // iteration on the x list
for (String s : ls) { // iteration on each intern list
System.out.println(s);
}
You can follow like...
List<List<String>> x = new ArrayList<List<String>>();
List<String> subX = x.get(7);
if(null != subX && subX.size() != 0) {
String element = subX.get(0);
}
//To directly access any list member using for loop instead of foreach loop
List<List<Integer>> list = new ArrayList<List<Integer>>();
for(int i=0;i<list.size();i++){
for(int j=0;j<list.get(i).size();j++){
do_something_on(list.get(i).get(j);
}
}
What is the most efficient way to search for a single element in an ArrayList of ArrayLists? Given the following:
ArrayList<ArrayList<Integer>> intList = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> a = new ArrayList<>();
a.add(1);
a.add(2);
ArrayList<Integer> b = new ArrayList<>();
b.add(3);
b.add(4);
intList.add(a);
intList.add(b);
How would I search to see if the ArrayList intList contains a specific Integer, like 3?
Just iterates trough all the lists and ask if any of them contain your value.
public boolean contains(int x, ArrayList<ArrayList<Integer>> listOfLists) {
for (ArrayList list: listOfLists) {
if (list.contains(x)) return true;
}
return false;
}
However, I agree with radai. There is probably the need for a more efficient data structure rather than an efficient algorithm
I'm working with Depth First Search program and I'm trying to create a Adjacency List Representation.
I read through some articles stating that an creating ArrayLists within an ArrayList would be the best representation.
Let's say I initialized the arraylist within a arraylist like so:
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
My question is how would you input data into the arraylist MANUALLY. I'm trying to understand the concept of arraylist with an arraylist before I begin my programming. If someone could possibly insert data into this arraylist so I could see the proper way of setting up.
Any additional input on anything I might need or take in consideration is recommended.
BTW: This is not a homework assignment just using personal time looking through my old textbooks.
Let's say you want to add 2 lists, one with 1 and 2 and the other with 10 and 20. A very manual way of adding could be:
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
adjList.add(new ArrayList<Integer>()); // initialise new ArrayList<Integer>
adjList.get(0).add(1); // add value one by one
adjList.get(0).add(2);
adjList.add(new ArrayList<Integer>());
adjList.get(1).add(10);
adjList.get(1).add(20);
You could also write it this way:
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
ArrayList<Integer> a1 = new ArrayList<Integer>(); // initialise new ArrayList<Integer>
a1.add(1); // add value one by one
a1.add(2);
adjList.add(a1);
ArrayList<Integer> a2 = new ArrayList<Integer>(); // initialise new ArrayList<Integer>
a2.add(10); // add value one by one
a2.add(20);
adjList.add(a2);
Well, a list of a list of Integer objects could be done as such:
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
List<Integer> li = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
li.add(i);
}
adjList.add(li);
Add to each sublist, and then add the sublist.
The adjList can contain the elements of the type List<Integer>, so create one and add using add(E element) function as we would for adding an element:
ArrayList<Integer>aList = new ArrayList<>();
adjList.add(aList);
Then to add an element to the element(which has the type List<Integer>) of adjList: you can try getting it using get(index) and add your element:
adjList.get(0).add(10);
adjList.get(0).add(22);
Try adding a second list and get it's index using get(1) and add the Integer element to the list at index 1 as the above example suggest. There are other known function too. Please check the class ArrayList<E> documentation page.
This will help
public static void main(String[] args){
//creating a new ArrayList of List of Integers
ArrayList<List<Integer>> integerListContainer = new ArrayList<List<Integer>>();
//Creating the first child arraylist of Integers
ArrayList<Integer> firstChildintegerList = new ArrayList<Integer>();
//filling the values 1,2,3 in it
firstChildintegerList.add(1);
firstChildintegerList.add(2);
firstChildintegerList.add(3);
//adding this integer list to the parent list
integerListContainer.add(firstChildintegerList);
//Creating the second child arraylist of Integers
ArrayList<Integer> secondChildintegerList = new ArrayList<Integer>();
//filling the values 10,20,30 in it
secondChildintegerList.add(10);
secondChildintegerList.add(20);
secondChildintegerList.add(30);
//adding this integer list to the parent list
integerListContainer.add(secondChildintegerList);
System.out.println("Printing the parent list to see what it has: ");
System.out.println(integerListContainer.toString());
}
Hope it clearly explains what happens