Why does this ArrayList act like a pointer?I thought all variables in java are refere

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • blazedaces
    Contributor
    • May 2007
    • 284

    Why does this ArrayList act like a pointer?I thought all variables in java are refere

    Before we begin let me say that I already found the solution to the problem, but I am still unable to explain why it solved the problem, so I am here to ask you experts why this java code produces the results I indeed see.

    The two pairs of code I am going to show are meant to find all the prime factors of a number (it is not my original code, I took it from Project Euler, and I'm further using it solve a later, harder problem in the project, but that is not relevant).

    I am going to post the first code and its corresponding incorrect result, then show the second code, its correct result, and I will lastly point out the only line that is different between the two.

    The question I have for you guys, because I can't answer it, is why is the first result coming up this way? Why does the solution of changing that single line of code work?

    The only explanation I can give is that for some reason if you initiate an ArrayList by saying ArrayList something = oldArrayList they are both pointing to the same ArrayList... I'm not satisfied with this answer because it doesn't make sense with the java structure I thought I knew.

    So here we go:
    First Code:
    Code:
    	public static void main(String[] args) {
    		utils.print(allPrimeFactorsAndTheirPowers(10));
    	}
    	
    	public static HashMap<Integer, Integer> allPrimeFactorsAndTheirPowers(int input) {
    		ArrayList<Integer> primeFactors = new ArrayList<Integer>((int)Math.sqrt((double)input));
    		ArrayList<Integer> powers = primeFactors;
    		HashMap<Integer, Integer> factorsAndPowers = new HashMap<Integer,Integer>((int)Math.sqrt((double)input));
    		int currentPower = 0;
    		
    		if (!isPrime(input)) {		
    			int n = input;
    			
    			if(n % 2 == 0) {
    				currentPower++;
    				primeFactors.add(Integer.valueOf(2));
    				n = n / 2;
    				while(n % 2 == 0) {
    					currentPower++;
    					n = n / 2;
    				}
    				powers.add(Integer.valueOf(currentPower));
    				currentPower=0;
    			}
    			int factor = 3;
    			int maxFactor = (int)Math.sqrt((double) n);
    			while(n > 1 && factor <= maxFactor) {
    				if (n % factor == 0) {
    					currentPower++;
    					n = n / factor;
    					primeFactors.add(factor);
    					while(n % factor == 0) {
    						currentPower++;
    						n = n / factor;
    					}
    					maxFactor = (int)Math.sqrt((double)n);
    					powers.add(Integer.valueOf(currentPower));
    					currentPower=0;
    				}
    				factor = factor+2;
    			} if (n != 1) {
    				primeFactors.add(Integer.valueOf(n));
    				powers.add(Integer.valueOf(1));
    			}
    		} else {
    			primeFactors.add(Integer.valueOf(input));
    			powers.add(Integer.valueOf(1));
    		}
    		
    		for(int i = 0; i < primeFactors.size(); i++) {
    			factorsAndPowers.put(primeFactors.get(i), powers.get(i));
    		}
    		
    		return factorsAndPowers;
    	}
    Incorrect Result:
    5 : 5
    1 : 1
    2 : 2


    Second Code:
    Code:
    	public static void main(String[] args) {
    		utils.print(allPrimeFactorsAndTheirPowers(10));
    	}
    	
    	public static HashMap<Integer, Integer> allPrimeFactorsAndTheirPowers(int input) {
    		ArrayList<Integer> primeFactors = new ArrayList<Integer>((int)Math.sqrt((double)input));
    		ArrayList<Integer> powers = new ArrayList<Integer>((int)Math.sqrt((double)input));
    		HashMap<Integer, Integer> factorsAndPowers = new HashMap<Integer,Integer>((int)Math.sqrt((double)input));
    		int currentPower = 0;
    		
    		if (!isPrime(input)) {		
    			int n = input;
    			
    			if(n % 2 == 0) {
    				currentPower++;
    				primeFactors.add(Integer.valueOf(2));
    				n = n / 2;
    				while(n % 2 == 0) {
    					currentPower++;
    					n = n / 2;
    				}
    				powers.add(Integer.valueOf(currentPower));
    				currentPower=0;
    			}
    			int factor = 3;
    			int maxFactor = (int)Math.sqrt((double) n);
    			while(n > 1 && factor <= maxFactor) {
    				if (n % factor == 0) {
    					currentPower++;
    					n = n / factor;
    					primeFactors.add(factor);
    					while(n % factor == 0) {
    						currentPower++;
    						n = n / factor;
    					}
    					maxFactor = (int)Math.sqrt((double)n);
    					powers.add(Integer.valueOf(currentPower));
    					currentPower=0;
    				}
    				factor = factor+2;
    			} if (n != 1) {
    				primeFactors.add(Integer.valueOf(n));
    				powers.add(Integer.valueOf(1));
    			}
    		} else {
    			primeFactors.add(Integer.valueOf(input));
    			powers.add(Integer.valueOf(1));
    		}
    		
    		for(int i = 0; i < primeFactors.size(); i++) {
    			factorsAndPowers.put(primeFactors.get(i), powers.get(i));
    		}
    		
    		return factorsAndPowers;
    	}
    Correct Result:
    5 : 1
    2 : 1

    The only line that changes:
    Incorrect Line of Code:
    Code:
    ArrayList<Integer> powers = primeFactors;
    Correct Line of Code:
    Code:
    ArrayList<Integer> powers = new ArrayList<Integer>((int)Math.sqrt((double)input));
    Your help and knowledge is much appreciated,
    -blazed
  • blazedaces
    Contributor
    • May 2007
    • 284

    #2
    I believe I found the answer:

    "Array variables are references to a block of elements

    When you declare an array variable, Java reserves only enough memory for a reference (Java's name for an address or pointer) to an array object. References typically require only 4 bytes. When an array object is created with new, a reference is returned, and that reference can then be assigned to a variable. When you assign one array variable to another, only the reference is copied. For example,

    int[] a = new int[] {100, 99, 98}; // "a" references the array object.
    int[] b; // "b" doesn't reference anything.

    b = a; // Now "b" refers to the SAME array as "a"
    b[1] = 0; // Also changes a[1] because a and b refer to the same array." - http://www.leepoint.net/notes-java/d...ys/arrays.html

    I had no idea this was the case, but it explains another problem I was having with arrays this time, and it completely explains what happened above.

    -blazed

    Comment

    Working...