Understanding the logic behind clear() in ArrayList - java

I am using below program to find the subsequences in an given given list. When I am using clear() , the values in li is also getting cleared. Hence, I am creating a new reference everytime.
I wanted to understand the logic behind this. Am I using it wrong? Or it is the reference that I am adding to my li?
public static int getTheSubseq(List<Integer> AList){
// int[][] subsequences = new int[][];
List<List<Integer>> li = new ArrayList<>();
List<Integer> temp = new ArrayList<>();
for (int i = 0; i < AList.size(); i++){
for(int j =i+1; j < AList.size(); j++){
temp.add(AList.get(i));
temp.add(AList.get(j));
li.add(temp);
temp = new ArrayList<>();
//temp.clear();
}
}
System.out.println(li);
return 1;
}

Regardless of whether or not you are calling temp.clear(), if you add to li multiple times a reference to the same List object, li will contain multiple references to the same List object, which means li.get(0) == li.get(1), li.get(0) == li.get(2), and so on...
Making changes in one of these inner Lists will be reflected in all the other inner Lists, since there's just one List referenced multiple times.
Therefore, assigning a new ArrayList instance to temp in each iteration of your loop (before adding it to li) is the right thing to do.
I'd make a slight change though - create the new inner List just before adding it to the outer List:
for (int i = 0; i < AList.size(); i++){
for(int j =i+1; j < AList.size(); j++){
List<Integer> temp = new ArrayList<>();
temp.add(AList.get(i));
temp.add(AList.get(j));
li.add(temp);
}
}

Adding the element to li doesn't make a copy. So when you call clear() you'll have both temp and an element inside li that point to the same object.
You may want to just declare temp inside the inner loop, so you get a fresh one every time without needing to call clear().

When you call .clear() (or any other method for that matter), you're operating on the same refernece.
Here, if you don't create a new list each iteration, you're adding the list referenced to by temp to li. When you call clear(), they are "all" cleared, since they all point to the same object.
When you create a new list each iteration, you have different objects, and can operate on them independently.

Try doing this:
public static int getTheSubseq(List<Integer> AList){
// int[][] subsequences = new int[][];
List<List<Integer>> li = new ArrayList<>();
List<Integer> temp;
for (int i = 0; i < AList.size(); i++){
for(int j =i+1; j < AList.size(); j++){
temp = new ArrayList<>();
temp.add(AList.get(i));
temp.add(AList.get(j));
li.add(temp);
}
}
System.out.println(li);
return 1;
}

Related

Error with adding element to list - repeating n-time last element

Could anyone help me and point out what is wrong here? All the fields are non-static. Function shuffle returns each time different array.
List<Point[]> someArray = new ArrayList<Point[]>();
for(int i = 0; i < 4; i++) {
Point[] temporary = new Point[50];
temporary = shuffle(pointsArray.getPoints());
someArray.add(temporary);
print(someArray.get(i));
}
The result of print in the first loop is ok since they're different. Right after getting out of the loop, I want to print elements of list someArray again.
for(int i = 0; i < 4; i++) {
print(someArray.get(i));
}
The result here is 4 time of the last element.

If condition inside nested for loop in android

I have two ArrayLists of the same model class (i.e ListA and ListB) to which I have added the same data.
Then I added some data only in the second arraylist ListB.
Now, I want to fetch only that data which is different in both ListA and ListB and store the result in a third arraylist ListC.
I tried below code. However, all elements are stored in ListC, as opposed to only those that are different:
ArrayList<C> ListC = new ArrayList<>();
for (int i = 0; i < ListA.size(); i++) {
for (int j = 0; j < ListB.size(); j++) {
if (ListA.get(i).getName() == ListB.get(j).getName()) {
Log.e("Do", "Nothing");
} else {
C c = new C(b.get(j).getName());
ListC.add(c);
}
}
}
Edited Question
ArrayList<Model> a = new ArrayList<>();
Model model = new Model();
model.setName("MaHi");
model.setAge("20");
a.add(model);
ArrayList<Model> b = new ArrayList<>();
Model model = new Model();
model.setName("MaHi");
model.setAge("20");
b.add(model);
Model model2 = new Model();
model2.setName("Ritu");
model2.setAge("21");
b.add(model2);
ArrayList<Model> c=new ArrayList<>();
now I want to fetch that data which is not in either arraylist a or arraylist b (i.e. data of model2) into arraylist of c;
The problem is that you are iterating over all combinations.
Lets say A = [1, 2, 3] and B = [1, 3, 4].
Then, your loop would compare
a=1 with b=1. Both are equal, nothing is done. That's good.
a=1 with b=3. They are not equal, so 3 is added to C. Here is your first problem: 3 actually is in A, but just not in your current iteration.
a=1 with b=4. They are not equal, so 4 is added to C. In this case, this is okay, since 4 is not in A.
a=2 with b=1. They are not equal, so 1 is added to C. However, 1 is actually in A.
and so on
Do you see how your solution does not work? You cannot compare every combination. Instead, you have to check for every element in B, if it is in A. If no, add.
This, directly translated to pseudo code, looks like
// for every element in ListB
for (int i = 0; i < ListB.length(); i++) {
B b = ListB.get(i);
// if this is not in ListA
if (!ListA.contains(b))
ListC.add(b);
}
However, here you should use the for-each loop for (B b: ListB).
And even better, simply use ListC.addAll(ListB); ListB.removeAll(ListA).
(And make sure hashCode and equals are properly written - but that is a different issue.)
Of course, this requires that the Elements in ListA and ListB are of the same type. See Jekin's answer for a solution using less standard library methods that also works with different types (as long as both implement getName(), of course).
This also resolves a second issue, as stated in the comments on your question: You cannot compare Strings with ==, but have to use the equals method. Try x = new String("a"); y = new String("a"); assert(x==y); and assert(x.equals(y));
As you have different class model(A,B) for all list, contains and remove methods might not be helpful for you, so you can use a flag contained like this:
Arraylist<C> ListC = new ArrayList<>();
for (int i = 0; i < ListB.size(); i++) {
// initially, assume that this element is not contained in ListA
boolean contained = false;
// check if this element is contained in ListA
for (int j = 0; j < ListA.size(); j++) {
if (ListA.get(i).getName().equals(ListB.get(j).getName())) {
contained = true;
}
}
// if this element is not contained once in ListA,
if (!contained) {
// add it to ListC
C c = new C();
c.setName(b.get(j).getName());
ListC.add(c);
}
}
This flag indicates, for every element in ListB, if it is contained at least once in ListA.
This ensures that each element in ListB is added at most once—your loop could add each element multiple times.
The problem is here in your code
if (ListA.get(i).getName() == ListB.get(j).getName()) {
Log.e("Do", "Nothing");
} else {
C c = new C();
c.setName(b.get(j).getName());
ListC.add(c);
}
You are using == operator to compare String values. Which is used for reference comparison not value comparison. While this may produce accurate results in many different programming languages but Java handles value comparisons differently. You need to use equals() or equalsIgnoreCase method instead of ==.
So change the line to
if (ListA.get(i).getName().equals(ListB.get(j).getName()))
Note : An == operator can sometimes produce correct results but only because the different Strings' references share the same object not because they have the same value.
Try below code
Arraylist<C> ListC = new ArrayList<>();
for (int i = 0; i < ListA.size(); i++) {
for (int j = 0; j < ListB.size(); j++) {
if (ListA.get(i).getName().equals(ListB.get(j).getName())) {
Log.e("Do", "Nothing");
} else {
C c = new C();
c.setName(b.get(j).getName());
ListC.add(c);
}
}
}
Just let me know if it doesn't resolve your need
i will definitely help you
public static void main(String arg[])
{
ArrayList<String> a=new ArrayList<>();
a.add("hello");
a.add("hi");
a.add("stack");
a.add("overflow");
a.add("empty");
a.add("world1");
ArrayList<String> b=new ArrayList<>();
b.add("hello");
b.add("hi");
b.add("stack");
b.add("overflow");
b.add("empty");
b.add("world");
ArrayList<String> c=new ArrayList<>();
int flag=0;
System.out.println(a.contains("empty"));
for (int i = 0; i < a.size(); i++) {
if(b.contains(a.get(i)))
{
}
else
{
System.out.println("haii");
c.add(a.get(i));
}
}
System.out.println(c.toString());
}
you try this example

Removing one object from multiple ArrayLists

Is there a way to make it so that, by deleting one object from one ArrayList, it deletes it from all the other ArrayLists that it exists in?
So for example in the code below, if I deleted everything from the ArrayList fives, the ArrayList test1 would contain no NumHolders that contained the value 5.
public static void main(String[] args) throws FileNotFoundException{
ArrayList<NumHolder> test1 = new ArrayList<NumHolder>();
ArrayList<Five> fives = new ArrayList<Five>();
String all = null;
for (int i = 0; i < 90; i++){
NumHolder number = new NumHolder(i);
test1.add(number);
if(i%5==0){
fives.add(number);
}
for (int j = 0; j < fives.size();j++){
fives.remove(0);
}
for (int j = 0; j < test1.size();j++){
test1.get(j).toString();
}
}
its easier than that my friend, just don't add the number numbers that divides on 5 without a reminder to your test1 ArrayList.
ArrayList<NumHolder> test1 = new ArrayList<NumHolder>();
ArrayList<Five> fives = new ArrayList<Five>();
String all = null;
for (int i = 0; i < 90; i++){
NumHolder number = new NumHolder(i);
if(i%5==0){
fives.add(number);
continue;
}
test1.add(number);
}
for (int j = 0; j < fives.size();j++){
fives.remove(0);
}
for (int j = 0; j < test1.size();j++){
test1.get(j).toString();
}
If you want to remove all 5s from both lists just use:
test1.removeAll(fives);
fives.clear();
One thing you could do is, instead of removing your elements from fives, keep them in that list and use the list in a single call on all the other lists:
test1.removeAll(fives);
If you don't want that - if there are too many lists and you don't want to call removeAll() on each list, and you really want all lists to share the elements, then you could wrap the elements in a class that contains a single member variable. Then set the member variable in the wrapper to null, instead of deleting it. Then all lists will be referring to the same wrapper element whose contained value was set to null.

How do I loop thorough a 2D ArrayList in Java and fill it?

I am trying to use 2D arrayLists in Java.
I have the definition:
ArrayList<ArrayList<Integer>> myList = new ArrayList<ArrayList<Integer>>();
How can I loop through it and enter in numbers starting from 1?
I know that I can access a specific index by using:
myList.get(i).get(j)
Which will get the value. But how do I add to the Matrix?
Thanks
You can use a nested for loop. The i-loop loops through the outer ArrayList and the j-loop loops through each individual ArrayList contained by myList
for (int i = 0; i < myList.size(); i++)
{
for (int j = 0; j < myList.get(i).size(); j++)
{
// do stuff
}
}
Edit: you then fill it by replacing // do stuff with
myList.get(i).add(new Integer(YOUR_VALUE)); // append YOUR_VALUE to end of list
A Note: If the myList is initially unfilled, looping using .size() will not work as you cannot use .get(SOME_INDEX) on an ArrayList containing no indices. You will need to loop from 0 to the number of values you wish to add, create a new list within the first loop, use .add(YOUR_VALUE) to append a new value on each iteration to this new list and then add this new list to myList. See Ken's answer for a perfect example.
Use for-each loop, if you are using Java prior 1.5 version.
for(ArrayList<Integer> row : myList) {
for(Integer intValue : row) {
// access "row" for inside arraylist or "intValue" for integer value.
}
}
Assuming the matrix is not initialized,
int m = 10, n = 10;
ArrayList<ArrayList<Integer>> matrix = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < m; i++) {
List<Integer> row = new ArrayList<Integer>();
for (int j = 0; j < n; j++) {
row.add(j);
}
matrix.add(row);
}

Clear() function for Arraylist in Arraylist

I am trying to add an arraylist in an arraylist in a for loop. When I clear the data in second one, it clears in second arraylist data in first arraylist. Let me explain with code:
ArrayList arrTemp = new ArrayList();
ArrayList arrTemp2 = new ArrayList();
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
//Here I add some strings in arrTemp
}
arrTemp2.add(arrTemp); //I will add arrTemp 10 times with different data in it to arrTemp2
arrTemp.clear(); //Everytime I want to clear the arrTemp
//But when I clear it, it also clears already added arrTemp in arrTemp2
}
I want it to have 10 different arrTemp in arrTemp2
for(int i = 0; i < 10; i++)
{
arrTemp = new ArrayList();
for(int j = 0; j < 10; j++)
.....
You will have different array for each i.
arrTemp2.add(arrTemp);// will add arrTemp object's reference to your arrTemp2.
So, once you clear arrTemp, you actually will clear() the space being pointed by arrTemp.
use Generics with addAll(), like this:
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(1);
al.add(2);
ArrayList<Integer> al2 = new ArrayList<Integer>();
al2.add(3);
al.addAll(al2);
al2.clear();
System.out.println(al);
}
O/P :
[1, 2, 3]
Your case :
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add(1);
al.add(2);
ArrayList al2 = new ArrayList();
al2.add(3);
al.add(al2);
al2.clear();
System.out.println(al);
}
O/P :
[1, 2, []] // 3rd item is considered as an Object
I'm not positive, but it seems to me that your addTemp2.add(arrTemp) is not working as intended. Have you tried debugging and checking whether arrTemp2 is actually being populated with something after that line fires? Looking at the documentation (below) for ArrayLists, I think you might want addAll instead. Alternately, you could iterate over arrTemp and add each element individually to arrTemp2 before you clear arrTemp.
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
Easy..
Replace
arrTemp.clear(); with arrTemp = new ArrayList();

Categories

Resources