Showing posts with label swap. Show all posts
Showing posts with label swap. Show all posts

Saturday, 30 April 2011

Passing by reference doesn't swaps in java

Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.
Take the badSwap() method for example:
public void badSwap(int var1, int var2)
{
int temp = var1;
var1 = var2;
var2 = temp;
}
public void badSwap2(Point arg1,Point arg2)
{
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}

The method successfully alters the value of pnt1, even though it is passed by value; however, a swap of pnt1 and pnt2 fails! This is the major source of confusion. In the main() method, pnt1 and pnt2 are nothing more than object references. When you pass pnt1 and pnt2 to the tricky() method, Java passes the references by value just like any other parameter. This means the references passed to the method are actually copies of the original references.



Java copies and passes the reference by value, not the object. Thus, method manipulation will alter the objects, since the references point to the original objects. But since the references are copies, swaps will fail. Unfortunately, after a method call, you are left with only the unswapped original references. For a swap to succeed outside of the method call, we need to swap the original references, not the copies.

But still it is not impossible to write swap. See here for this.

Writing a swap function in java

Method 1 : Changing the data underneath
public class Swapper<T> {
     
public Swapper(T obj) {
             data_
= obj;
     
}
     
public T get() { return data_; }
     
public void set(T value) { data_ = value; }
     
public void swap(Swapper<T> o) {
           T tmp
= o.data_;
           o
.data_ = data_;
           data_
= tmp;
     
}
     
private T data_ = null;
 
}

 
// .. Now you can do:
 
Swapper<String> a = new Swapper("Hello");
 
Swapper<String> b = new Swapper("World");
 
// a.get().equals("Hello")
  a
.swap(b); // now a.get().equals("World")


But we can write function which uses the above idea:
public void Swap(RefObject<Integer> p, RefObject<Integer> q)
{
   
int temp;
   temp
= p.argvalue;
   p
.argvalue = q.argvalue;
   q
.argvalue = temp;
}
public final class RefObject<T>
{
   
public T argvalue;
   
public RefObject(T refarg)
   
{
        argvalue
= refarg;
   
}
}


Method 2 : Using Atomic reference
Example for integers:

public void swap(AtomicInteger a, AtomicInteger b){
   
  a.set(b.getAndSet(a.get()));
}
  

Above method can be written in more verbose way like this:

import java.util.concurrent.atomic.AtomicInteger;
public class TestAtomicInteger{
   
private static void swap(AtomicInteger a, AtomicInteger b) {
       
int val = a.get();
        a
.set(b.get());
        b
.set(val);
   
}

   
public static void main(String[] args) {
       
AtomicInteger a = new AtomicInteger(1);
       
AtomicInteger b = new AtomicInteger(2);

        swap
(a, b);

       
System.out.println("a: " + a + " b: " + b);
   
}
}

Example for strings:
public void swap(AtomicReference a, AtomicReference b){
        a.set(b.getAndSet(a.get()));
}


Of course this not very satisfactory, as you hardly ever develop against AtomicReferences. But basically you need to use some kind of container as shown above, because you can't just swap the references. So you can e.g. swap the elements of a two-element array or list, but you just can't swap two strings without having access to the original variables (so you can't do it in a helper function).

Case when data is in list:
If your data happens to be a List, a better way to swap is to use Collections.swap(List, int, int).
In above function following are the function and parameters:

Swaps the elements at the specified positions in the specified list.
(If the specified positions are equal, invoking this method leaves
the list unchanged
.)
Parameters:
    list
- The list in which to swap elements.
    i
- the index of one element to be swapped.
    j
- the index of the other element to be swapped.

Case when swap is required in sorting:
apparently the real objective is to sort an array of ints. That's a one-liner with Arrays.sort(int[]):

int[] arr = {2,3,1,378,19,25};
Arrays.sort(arr);

To check the output:
   System.out.println(Arrays.toString(arr));
   // [1, 2, 3, 19, 25, 378]

And here is a simple helper function to swap two positions in an array of ints:

public static void swap(final int[] arr, final int pos1, final int pos2){
   final int temp = arr[pos1];
   arr[pos1] = arr[pos2];
   arr[pos2] = temp;
}

Best Way to Swap Values in Java

Though not all Java applications require variables to be swapped, but those which do require are not given proper thoughts about correct and optimized implementation.


Method-1: Using temporary Variable

The most common way to swap two values is by using a temporary variable as shown below:

int a=10,b=5,c;
c=a; (c=10,a=10,b=5)
a=b; (c=10,a=5,b=5)
b=c; (c=10,a=5,b=10)

If the use of temporary variable c is not allowed, then we have the following two options:

Method-2.1 : Using the addition and subtraction operations
int a=10,b=5;
a=a+b;
b=a-b;
a=a-b

The problem with the above solution is that the addition and subtraction can cause overflows. An overflow is a condition when the value of a variable is increased/decreased beyond the maximum/minimum value of that variable. Though the output of such a program may show that the variables have been swapped but it is not guaranteed as per Specification of various programming languages including Java.

package com.vaani.swap.subtraction;
class Test{
    public static void main (String args[]) {
            int a=1999999999,b=1899999999;
            a = a + b;
            System.out.println("After operation 1, a = " + a +
                 " b = " + b);
            b = a - b;
            System.out.println("After operation 2, a = " + a +
                 " b = " + b);
            a = a - b;
            System.out.println("After operation 3, a = " + a +
                 " b = " + b);
   }
}

Output:
After operation 1, a =  -394967298 b = 1899999999
After operation 2, a =  -394967298 b = 1999999999
After operation 3, a =  1899999999 b = 1999999999

Method-3: Using the XOR operator

The XOR operator can also be used swap two variables using the logic shown below:

int a=10,b=5;
a=a^b;
b=a^b;
a=a^b

Thank you