So the issue I'm having is after copying the 2d arraylist, changing the element from one 2d arraylist affects the other 2d arraylist. I want them to be completely separate in memory.
First example shows how it works correctly with 1d arraylists...
import java.util.ArrayList;
public class QuickTest {
public static void main(String[] args) {
ArrayList<Integer> firstList = new ArrayList<>();
ArrayList<Integer> secondList = new ArrayList<>();
Integer counter = 2;
for(int arrI = 0; arrI < 4; arrI++, counter+=2){
firstList.add(counter);
}
secondList = new ArrayList<>(firstList);
System.out.println("firstList.get(2) = " + firstList.get(2));
System.out.println("secondList.get(2) = " + secondList.get(2));
firstList.set(2, 7);
System.out.println("firstList.get(2) = " + firstList.get(2));
System.out.println("secondList.get(2) = " + secondList.get(2));
}
}
Expected output:
Notice how the element from the first arraylist is changed but not the second arraylist element is not changed. This is good and what we want.
Now to try and copy the 2d arraylists...
import java.util.ArrayList;
public class QuickTest {
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> firstTwoDimList = new ArrayList<>();
ArrayList<ArrayList<Integer>> secondTwoDimList = new ArrayList<>();
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
Integer counter = 2;
for(int arrI = 0; arrI < firstTwoDimList.size(); arrI++, counter+=2){
firstTwoDimList.get(arrI).add(counter);
counter+=2;
firstTwoDimList.get(arrI).add(counter);
}
secondTwoDimList = new ArrayList<>(firstTwoDimList);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
firstTwoDimList.get(1).set(0, 7);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
}
}
Unexpected output:
Anyone have any idea what the reason for this is, and what the best solution would be?
This is what is happening in the 1D array list case, in terms of references:
This is what is happening in the 2D array list case:
This means that when you copy an array list using this:
new ArrayList<>(someOldArrayList)
the items themselves don't get copied, only a new array list object is created, referring to all the items in the old array list.
In the second case, you are only changing what array list 2's items are, but index 1 of first list and second list refers to the same array list 2.
To fix this, you need to copy the array lists inside first list and second list as well. One way to do this:
secondList = new ArrayList<>(firstList.stream().map(x -> new ArrayList<>(x)).collect(Collectors.toList()));
You should iterate through the size of the first dimension of the firstTwoDimArray and add new reference of each second dimension to the secondTwoDimArray. i.e.
for(int index = 0; index < firstTwoDimList.size(); index++) {
secondTwoDimList.add(new ArrayList<Integer>(firstTwoDimList.get(index)));
}
The difference between your first and second example is that in the second one you use get(). This get() returns a new variable, so you assign the integers to it and not to the original ArrayList.
If you want to assign a value:
firstTwoDimList.set(1, new ArrayList<Integer>(Arrays.asList(0, 7)));
I guess I was looking for something like this...
import java.util.ArrayList;
public class QuickTest {
public static ArrayList<ArrayList<Integer>> getTwoDimArrListCopy(ArrayList<ArrayList<Integer>> original){
ArrayList<ArrayList<Integer>> copy = new ArrayList<>();
for (ArrayList<Integer> arr: original){
copy.add(new ArrayList<Integer>(arr));
}
return copy;
}
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> firstTwoDimList = new ArrayList<>();
ArrayList<ArrayList<Integer>> secondTwoDimList = new ArrayList<>();
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
firstTwoDimList.add(new ArrayList<Integer>());
Integer counter = 2;
for(int arrI = 0; arrI < firstTwoDimList.size(); arrI++, counter+=2){
firstTwoDimList.get(arrI).add(counter);
counter+=2;
firstTwoDimList.get(arrI).add(counter);
}
secondTwoDimList = getTwoDimArrListCopy(firstTwoDimList);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
firstTwoDimList.get(1).set(0, 7);
System.out.println("firstTwoDimList.get(1).get(0) = " + firstTwoDimList.get(1).get(0));
System.out.println("secondTwoDimList.get(1).get(0) = " + secondTwoDimList.get(1).get(0));
}
}
I was just hoping there was a built in library that would do that getTwoDimArrListCopy() function for me...
Related
For example, there is an arraylist: 40 8 6 3 7 5 2, and I want to left shift them by 2 post. And then expected output is 6 3 7 5 2. I have wrote the following code, but it generate nothing
Code:
import java.util.ArrayList;
class ArrayLinearListRev extends ArrayLinearList{
public ArrayList<Integer> leftSh(int post, ArrayList<Integer>
alist2)
{
ArrayList<Integer> LeftshifedList = new ArrayList<Integer
();
for (int i = alist2.size(); i <= post; i++)
{
LeftshifedList.remove(alist2.get(i));
}
return LeftshifedList;
}
public void printElements(ArrayList<Integer> alist2)
{
for (int i = 0; i < alist2.size(); i++) {
System.out.print(alist2.get(i) + " ");
}
}
}
public class ArrayLinearListFun {
public static void main(String[] args)
{
ArrayLinearListRev obj = new ArrayLinearListRev();
ArrayList<Integer> x = new ArrayList<Integer>();
x.add(0, new Integer(2));
x.add(1, new Integer(5));
x.add(2, new Integer(7));
x.add(3, new Integer(3));
x.add(4, new Integer(6));
x.add(5, new Integer(8));
x.add(6, new Integer(40));
System.out.print("The list is: ");
obj.printElements(x);
x=obj.leftSh(2, x);
System.out.print("\nThe list is: ");
obj.printElements(x);
}
}
Your leftSh method returns an empty List. Assuming you don't want your method modify the original List, you should initialize LeftshifedList to be a copy of the original List.
You simply need to remove the element at index 0 and repeat post times.
public ArrayList<Integer> leftSh(int post, ArrayList<Integer> alist2)
{
ArrayList<Integer> LeftshifedList = new ArrayList<>(alist2); // create a copy of input List
for (int i = 1; i <= post; i++) { // remove the first post elements
LeftshifedList.remove(0);
}
return LeftshifedList;
}
Just remove first two elements.
public ArrayList<Integer> leftSh(int post, ArrayList<Integer> alist2) {
alist2.remove(0);
alist2.remove(0);
return alist2;
}
import java.io.*;
import java.util.*;
class Graph
{
private int V; // No. of vertices
private LinkedList<Integer> adj[]; //Adjacency Lists
private LinkedList<Integer> path[];
Graph(int v)
{
V = v;
adj = new LinkedList[v];
for (int i=0; i<v; ++i)
adj[i] = new LinkedList();
path = new LinkedList[v];
for(int i=0;i<v;++i)
adj[i]=new LinkedList();
}
void addEdge(int v,int w)
{
adj[v].add(w);
}
// prints BFS traversal from a given source s
void BFS(int s,int d)
{
boolean visited[] = new boolean[V];
LinkedList<Integer> queue = new LinkedList<Integer>();
visited[s]=true;
queue.add(s);
path[s].addLast(s);
while (queue.size() != 0)
{
s = queue.poll();
//System.out.print(s+" ");
Iterator<Integer> i = adj[s].listIterator();
while (i.hasNext())
{
int n = i.next();
if (!visited[n])
{
visited[n] = true;
queue.add(n);
path[n]=path[s];
path[n].addLast(n);
}
}
}
System.out.print("Following is the path from source to destination\n");
while(path[d].size()!=0)
{
int xyz=path[d].getFirst();
path[d].poll();
System.out.print(xyz+" ");
}
}
// Driver method to
public static void main(String args[])
{
Graph g = new Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
System.out.println("Following is the desired path\n");
g.BFS(2,3);
}
}
I need to get the shortest path between nodes 2 and 3.
You're attempting to add an element to a linked list that is null. You need to initialize the linked list at index s before you can add to it.
path[s] = new LinkedList();
path[s].addLast(s);
Additionally, your code is failing because you don't clone the path array when setting the value of path[n]:
path[n]=path[s];
You need to change this to:
path[n]= (LinkedList) path[s].clone();
This way the list for n won't retain a reference to the list of s. Currently, the reference is retained, so that whenever you add something to the list for n, that thing will also be added to s.
As there is no information what exactly isn't behaving as expected, it is a bit difficult to say what the error is. But I see two problems with the code:
First, you don't initialize the elements of the path. Instead, in the constructor you initialize the elements of adj twice. So, you should replace one of the lines that say
for(int i=0; i<v; ++i)
adj[i] = new LinkedList();
with
for(int i=0; i<v; ++i)
path[i] = new LinkedList();
or you can just delete the two lines as you will see now:
The second problem is that you set the different elements of path as the reference to another LinkedList and edit it:
path[n] = path[s];
path[n].addLast(n);
This has as result that every element of path uses the same LinkedList with the same elements. Instead you should create a new LinkedList containing the same elements:
path[n] = new LinkedList(path[s]);
path[n].addLast(n);
EDIT: As Soggiorno said in his answer, you must at least initialize path[s] at the beginning of the BFS-method before adding an element to it:
path[s] = new LinkedList();
path[s].addLast(s);
If you do the initialization for all the elements of path this isn't needed, of course.
Well im stuck on this point.
im trying to make sort function what does this.
parentarraylist = [1,1,1,2,3,2,3,3,2,2,1];
*magic*
childarraylist1 = [1,1,1,1];
childarraylist2 = [2,2,2,2];
childarraylist3 = [3,3,3];
the magic part is where im stuck.
i have tryied putting it in an for loop(the parent) and checking on the value. like this
int i = 0;
int finder = 0;
ArrayList<int> initArray = new ArrayList();
for(int list : parentarraylist){
if(i == 0){
finder = list
}
if(finder == list){
initArray.add(list);
parentarraylist.remove(list);
}else{
new ArrayList *value of list* = new ArrayList();
finder = list;
*value of list*.add(list);
}
}
this results in a view errors like
java.util.ConcurrentModificationException
and i cant set value of list
what can i do to make this work?
This little snippet should help you achieve your goal:
//maps will hold ALL unique integer as it's key
HashMap<Integer, ArrayList<Integer>> maps = new HashMap<Integer, ArrayList<Integer>>();
//your initial array, written inline for clarity
ArrayList<Integer> parentarraylist = new ArrayList<Integer>(Arrays.asList( new Integer[] {1,1,1,2,3,2,3,3,2,2,1}));
//get the iterator so that we won't need another temporary int variable for loop
Iterator<Integer> iterator = parentarraylist.iterator();
while(iterator.hasNext()){
//next = current integer in our array
Integer next = iterator.next();
//check if we have already have current integer or not
if(!maps.containsKey(next)){
//we don't have it, initialise an arraylist for this specific integer
ArrayList<Integer> x = new ArrayList<Integer>();
x.add(next);
//put it to our map holder
maps.put(next, x);
} else {
//already have it, add directly
maps.get(next).add(next);
}
}
This codes will print something like this:
printMap(maps);
//1 = [1, 1, 1, 1]
//2 = [2, 2, 2, 2]
//3 = [3, 3, 3]
printMap() is taken from this answer: Iterate through a HashMap
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
}
You could try something like this:
public static void main(String[] args) {
ArrayList<Integer> parent = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
parent.add(3);
parent.add(1);
parent.add(1);
parent.add(2);
parent.add(3);
parent.add(3);
parent.add(1);
for(int i : parent)
{
boolean check = false;
for(ArrayList<Integer> result : results)
{
if(result.size() > 0)
{
if(result.get(0) == i)
{
check = true;
result.add(i);
break;
}
}
}
if(!check)
{
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(i);
results.add(temp);
}
}
for(ArrayList<Integer> i : results)
{
for(int j : i)
{
System.out.print("" + j);
}
System.out.println();
}
}
Output:
333
111
2
The problem is that you remove an element from an array over which you are iterating. The
parentArrayList.remove(list);
causes the error here. If you remove this line your program will work. At the moment I do not see the benefit of removing the item from the parentArrayList for your sorting algorithm so just delete it and you are good to go.
i have an arrayList ( named error_dub ) i want to print the duplicates only one time here is my code
for(x=0 ; x<=error_dub.size()-1 ; x++){
for(int h=x+0 ; h<=error_dub.size() ; h++){
if(error_dub.get(x).equals(error_dub.get(h) && x!=h){
System.out.println(error_dub.get(x)+" is duplicated ");
}
}
}
here the line is printed more than once so how can i printed only once ?
Use two sets (this assumes X is the class of your object):
// Returns a set of all duplicates in a list
public Set<X> getDuplicates(final List<X> list)
{
final Set<X> dups = new HashSet<X>();
final Set<X> set = new HashSet<X>();
/*
* Cycle through all elements in the original list. Add it to "set":
*
* - if the .add() method returns true, this is the first time the element is seen;
* - if it returns false, then this is not the first time, it is a duplicate:
* add it to "dups".
*/
for (final X element: list)
if (!set.add(element))
dups.add(element);
return dups;
}
Set's .add() will return false if the set is not modified as a result of the operation, which means if the element was already there.
Copy/paste that function into your existing code and replace the snippet above with:
for (final X dup: getDuplicates(error_dub))
System.out.println(dup + " is duplicated");
Important note: the getDuplicates() function as it is written will NOT respect element order. If order matters to you, replace dups with a LinkedHashSet instead of a HashSet.
you can use .add() method of set to check for duplicates. Method posted below adds list elements to set1. If element is a duplicate (.add() returns true), then element is adde to setToReturn
public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{
final Set<Integer> setToReturn = new HashSet();
final Set<Integer> set1 = new HashSet();
for (Integer yourInt : listContainingDuplicates)
{
if (!set1.add(yourInt))
{
setToReturn.add(yourInt);
}
}
return setToReturn;
}
ArrayList<String> ar=new ArrayList<String>();
ArrayList<String> ar2=new ArrayList<String>();
ar.add("1");
ar.add("2");
ar.add("3");
ar.add("4");
ar.add("5");
ar.add("1");
ar.add("2");
ar.add("1");
for(int x=0;x<ar.size();x++)
{
if(!ar2.contains(ar.get(x)))
{
for(int y=x+1;y<ar.size()-1;y++)
{
if((ar.get(y).equals(ar.get(x))))
{
System.out.print("repeating "+ar.get(x));
ar2.add(ar.get(x));
break;
}
}
}
}
you can do like this.
//method to identify the duplicate elements in array list
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
public class Dup
{
public static void main(String[] args)
{
ArrayList<Integer> a=new ArrayList<Integer>();
System.out.println("enter elements");
int g;
Scanner b= new Scanner(System.in);
for(int i=0;i<10;i++)
{
g=b.nextInt();
a.add(g);
}
HashSet<Integer> c=new HashSet<Integer>();
ArrayList<Integer> d=new ArrayList<Integer>();
for (Integer y : a)
{
if (c.contains(y))
{
d.add(y);
}
else
c.add(y);
}
System.out.println("original elements are:"+c);
System.out.println("duplicate elements are:");
for(Integer h:d)
{
System.out.println(h);
}
}
}
Say I have an arraylist a with the values:
a[0] = G
a[1] = B
a[2] = D
I was wondering, how can I create a new arraylist in java, that joins index values at random places and puts it into a new arraylist b
So like:
b[0] = GB
b[1] = D
or
b[0] = G
b[1] = BD
or
b[0] = GBD
The order of the values is kept the same, it's just the different combinations of the joins, and at different places over different amounts.
Something like (pseudocode)
newA = new ArrayList<String>();
for (b : a) {
if (Math.random() > 0.5) newA.add(b);
else newA.set(previous, newA.get(previous) + b);
}
Assuming you can get the "random position" yourself, my thought would be to use something like the following:
import org.apache.commons.lang.StringUtils;
public List<String> mergeAt(ArrayList<String> input, int offset) {
List<String> result = new ArrayList<String>();
result.add(StringUtils.join(input.subList(0, offset), '');
result.add(StringUtils.join(input.subList(offset, input.size()), '');
return result;
}
First merge element at index i with index j:
yourList.set(i, yourList.get(i) + yourList.get(j));
Then remove element at index j:
yourList.remove(j);
This satisfies all the conditions you listed above. you can adjust joinIndex and joinSize to whatever you want and it will start at the joinIndex position and concatenate joinSize characters.
Fixed the issue with the exceeding bounds. Now it will just concat as many characters at the end as exist.
import java.util.ArrayList;
import java.util.List;
public class TestJoiner
{
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("G");
list.add("B");
list.add("D");
list.add("L");
list.add("G");
list.add("A");
//Get Random Int
int joinIndex=3;
int joinSize=2;
//check join size, make sure it doesn't exceed bounds.
joinSize=(joinIndex+joinSize+1)>list.size()?list.size()-joinIndex-1:joinSize;
//join
for(int a=joinIndex;a<joinIndex+joinSize;a++){
list.set(joinIndex,list.get(joinIndex)+list.get(a+1));
}
//shift
for(int c=joinIndex+1;c<list.size()-joinSize;c++){
list.set(c,list.get(c+joinSize));
}
//Truncate
list=list.subList(0,list.size()-joinSize);
System.out.println(list);
}
}
badger. Here is task solution. Just use List<String> Shaker.shake(List<String>) method.
Shaker class:
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
public class Shaker {
public static List<String> shake(List<String> sourceList) {
Random random = new Random();
// We'll use cloned original list
LinkedList<String> itemsList = new LinkedList<String>(sourceList);
// Count how much items need shaking
int itemsToMerge = itemsList.size();
// New generated list
List<String> newList = new ArrayList<String>();
// Temporary values, used in cycle
int firstGroupItemIndex = 0;
while (0 < itemsToMerge) {
// Select random number of merged items
int groupLength = random.nextInt(itemsToMerge) + 1;
// Create inserted string value
StringBuilder insertedValue = new StringBuilder();
int lastGroupItemIndex = firstGroupItemIndex + groupLength;
for (int i = firstGroupItemIndex; i < lastGroupItemIndex; i++) {
insertedValue.append(itemsList.removeFirst());
}
// Add merged string value
newList.add(insertedValue.toString());
firstGroupItemIndex = lastGroupItemIndex;
itemsToMerge -= groupLength;
}
return newList;
}
}
And Test class:
import java.util.List;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
List<String> originalList = new ArrayList<String>();
originalList.add("G");
originalList.add("B");
originalList.add("C");
originalList.add("L");
originalList.add("G");
originalList.add("A");
List<String> newList = Shaker.shake(originalList);
System.out.println("Original list: " + originalList);
System.out.println("Shaked list: " + newList);
}
}
Look at the result:
Original list: [G, B, C, L, G, A]
Shaked list: [GBC, LG, A]
If you have questions about the code, I'll answer you with pleasure.
You can always find solution sources at github.com.