50

how do I make my swap function in java if there is no method by which we can pass by reference? Could somebody give me a code?

swap(int a, int b)
{
     int temp = a;
     a = b;
     b = temp;
}

But the changes wont be reflected back since java passes parameters by value.

Ashutosh
  • 917
  • 10
  • 19
higherDefender
  • 1,551
  • 6
  • 23
  • 35
  • 3
    You'll have to state more specifically what you're trying to accomplish if you want to get help with this. – Nate C-K Mar 06 '10 at 19:59
  • 1
    Check out this article: http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html – Thomas Matthews Mar 06 '10 at 20:01
  • 1
    All parameters in Java are passed by value. – Travis Gockel Mar 06 '10 at 20:02
  • you should use Integer instead int. – GuruKulki Mar 06 '10 at 20:11
  • 5
    @gurukulki: That won't change a thing. If Integer had a `setValue` method, you could use that method instead of assignment and that would have the desired effect (unless you also want the object identity to change), but since there's not, using Integer won't help a bit. – sepp2k Mar 06 '10 at 20:15
  • 1
    Chk this out.More info on swap by reference. http://www.cs.utsa.edu/~wagner/CS2213/swap/swap.html Chk this out.More info on swap by reference. –  Jun 28 '12 at 07:23

8 Answers8

77

I think this is the closest you can get to a simple swap, but it does not have a straightforward usage pattern:

int swap(int a, int b) {  // usage: y = swap(x, x=y);
   return a;
}

y = swap(x, x=y);

It relies on the fact that x will pass into swap before y is assigned to x, then x is returned and assigned to y.

You can make it generic and swap any number of objects of the same type:

<T> T swap(T... args) {   // usage: z = swap(a, a=b, b=c, ... y=z);
    return args[0];
}

c = swap(a, a=b, b=c)
dansalmo
  • 11,506
  • 5
  • 58
  • 53
  • 3
    That is actually quite a nice idea. – Sunspawn Feb 28 '14 at 12:43
  • 6
    I agree, a nice idea, but dangerous too... As it relies on parameter assignment on invocation, any project featuring this method will sooner or later run into a bug because of it. Wouldn't allow that in production code if I was lead. – Franz D. Jul 23 '15 at 18:05
  • 7
    Clever. TOO clever. Relies on someone writing this pattern exactly correctly. Extremely non-obvious to read later. I would also veto such a piece of code in production. But I agree that it is very intriguing. So close... – ToolmakerSteve Sep 09 '15 at 18:56
  • i love the idea, but there are two replays says that code is critical and should not used in production, why ?? – Marzouk Sep 26 '15 at 01:22
  • 2
    Because it relies on parameter assignment on invocation, there is a fear that maybe somewhere, somehow, some implementation of Java might get it wrong. Also, as noted in my description, the usage pattern is not straightforward. – dansalmo Sep 26 '15 at 17:36
  • 6
    @deserthero You should also note, that the method name `swap` is a plain lie and it doesn't do what it is supposed to do. The idea might be nice, but this code shouldn't pass any code review. – Tom Oct 06 '15 at 17:28
  • 2
    This is very clever, but it is just a very bad horrible hack. Useful for golfing/obfuscating code, but nothing more. This should not be used in real-world code. I understand that you meant to solve the OPs problem, but in fact this function do not swap anything at all, it is just the side-effects of the parameters evaluation that does that. This should have a very big comment as: "*kids, do not try this at home*", otherwise newbies might think that this is a good practice (I was linked to here by one of those). The straightforward `{ temp = a; a = b; b = temp; }` is still much better. – Victor Stafusa - BozoNaCadeia Jun 08 '17 at 23:33
  • 1
    This signature would be way better: ` T swapHackSeeDocBlock(T... args)` – pilat Dec 18 '17 at 05:06
  • 1
    This function takes two arguments and always returns the first one. It's the Kestrel combinator in SKI combinator calculus. – joseville Nov 12 '21 at 14:48
27

You can't create a method swap, so that after calling swap(x,y) the values of x and y will be swapped. You could create such a method for mutable classes by swapping their contents¹, but this would not change their object identity and you could not define a general method for this.

You can however write a method that swaps two items in an array or list if that's what you want.

¹ For example you could create a swap method that takes two lists and after executing the method, list x will have the previous contents of list y and list y will have the previous contents of list x.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 7
    You can create a [method](http://stackoverflow.com/questions/2393906/how-do-i-make-my-swap-function-in-java/20600020#20600020) called as `y = swap(x, x=y)` to swap x and y. – dansalmo Dec 15 '13 at 21:44
16

It depends on what you want to do. This code swaps two elements of an array.

void swap(int i, int j, int[] arr) {
  int t = arr[i];
  arr[i] = arr[j];
  arr[j] = t;
}

Something like this swaps the content of two int[] of equal length.

void swap(int[] arr1, int[] arr2) {
  int[] t = arr1.clone();
  System.arraycopy(arr2, 0, arr1, 0, t.length);
  System.arraycopy(t, 0, arr2, 0, t.length);
}

Something like this swaps the content of two BitSet (using the XOR swap algorithm):

void swap(BitSet s1, BitSet s2) {
  s1.xor(s2);
  s2.xor(s1);
  s1.xor(s2);
}

Something like this swaps the x and y fields of some Point class:

void swapXY(Point p) {
  int t = p.x;
  p.x = p.y;
  p.y = t;
}
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • are arrays passed by reference? – higherDefender Mar 06 '10 at 20:05
  • No. Everything in Java is passed by value, including _references to_ arrays in Java. Arrays are no different than any other objects in this case. – polygenelubricants Mar 06 '10 at 20:06
  • 3
    @D.J.: Arrays (like all objects) are reference-types. This means that any changes made to the object inside a method will be visible on the outside (it also means that passing an object to a method does not copy the object's contents, so passing a 1M-element array does not copy 1M objects). However reassigning the variable that refers to the array will not be visible on the outside (meaning if you do something like `arr1 = arr2` inside the method, this will not have any visible effect on the outside). – sepp2k Mar 06 '10 at 20:09
9

Apparently I don't have enough reputation points to comment on Dansalmo's answer, but it is a good one, though mis-named. His answer is actually a K-combinator.

int K( int a, int b ) {
    return a;
}

The JLS is specific about argument evaluation when passing to methods/ctors/etc. (Was this not so in older specs?)

Granted, this is a functional idiom, but it is clear enough to those who recognize it. (If you don't understand code you find, don't mess with it!)

y = K(x, x=y);  // swap x and y

The K-combinator is specifically designed for this kind of thing. AFAIK there's no reason it shouldn't pass a code review.

My $0.02.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • 3
    Now that you have enough reputation, please move this into a comment. Thanks! – Nic Mar 24 '16 at 17:10
  • I agree, please add your comment above. I was actually heavily into learning functional techniques at the time and may have unknowingly applied them without recognizing the pattern. You might also find this interesting. http://pure-fn.appspot.com/about – dansalmo Dec 19 '17 at 15:33
  • 1
    That's a nice trick, but i don't think that it improves readability. I you sum up the words used to explain the trick, you barely gain anything over "int aux=a; a=b; b=aux;" – Raúl Salinas-Monteagudo Apr 11 '19 at 06:37
  • That's why I called it "returnFirst" instead of "swap" in my original answer (see "Is it possible to write swap method in Java?" – I think I had put a direct link here somewhere but I can't find it anymore). I didn't know the K-combinator tho. As I explain in my answer, what you gain is: single statement and no variable declaration so your code is more compact and conceptually cleaner. Suppose you need to swap all the inner guts of an object, swapping all of its members: using returnFirst there's no need for intAux, longAux, objAux, etc. and less risk of using the wrong variable somewhere. – marcus Jan 31 '23 at 13:13
2

AFAIS, no one mentions of atomic reference.

Integer

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

String

public void swap(AtomicReference<String> a, AtomicReference<String> b){
    a.set(b.getAndSet(a.get()));
}

As per @Stephan's comment: as long as you are not in a multi-threaded app, the following will work as well.

First: wrap your simple types in an array of size 1.

int[] x1 = {x};
int[] y1 = {y};

Then write a swap method

public void swap(int[] a, int[] b) {
    assert(a.length == 1);
    assert(b.length == 1);
    int temp = a[0];
    a[0] = b[0];
    b[0] = temp;
}

If you want to make this work for all simple types, you'll have to write overloads, because Java Generics don't work for simple types.

Johan
  • 74,508
  • 24
  • 191
  • 319
  • 1
    You don't need an atomic type to do this. Any mutable holder class will do. Even one-element arrays of primitives or references. – Stephen C Jan 30 '17 at 12:16
1

I might do something like the following. Of course, with the wealth of Collection classes, i can't imagine ever needing to use this in any practical code.

public class Shift {
  public static <T> T[] left (final T... i) {
    if (1 >= i.length) {
      return i;
    }
    final T t = i[0];
    int x = 0;
    for (; x < i.length - 1; x++) {
      i[x] = i[x + 1];
    }
    i[x] = t;
    return i;
  }
}

Called with two arguments, it's a swap.

It can be used as follows:

int x = 1;
int y = 2;
Integer[] yx = Shift.left(x,y);

Alternatively:

Integer[] yx = {x,y};
Shift.left(yx);

Then

x = yx[0];
y = yx[1];

Note: it auto-boxes primitives.

nicerobot
  • 9,145
  • 6
  • 42
  • 44
  • Tempted to downvote you, since (a) it doesn't really help - the result is an array; the original x,y are still not swapped. (b) swap is such a common operation, that one would write a custom function to swap, not use this more general-purpose shift function. – ToolmakerSteve Sep 09 '15 at 18:46
  • 1
    @ToolmakerSteve Did you happen to notice that a standard swap was already provided as well as a proper answer, that it isn't possible in a standard way? So rather than clone the already provided answer, my answer is a different "kind" of swap. The point of answers is to provide options, not just for everyone to regurgitate the same answer over and over. So using a shift for a swap is a valid type of swap and wasn't an already provided answer, so i submitted it. – nicerobot Sep 09 '15 at 18:52
  • I still disagree: it isn't useful in the context of the question. Maybe in some different question. And the observations I made stand. However, as I said, my disagreement is not strong enough to downvote your answer. – ToolmakerSteve Sep 09 '15 at 19:16
  • And I am amused that this 5 year old answer, in the same 10 minute span that you responded to my comment, gained a +1 on your answer, and also a +1 on your comment. Two accounts? Or called in a friend for reinforcement? – ToolmakerSteve Sep 09 '15 at 19:21
  • @ToolmakerSteve Your disagreement is noted. But since there is definitely one person in the world, Me, who can see the utility in this answer in the context of the question, it makes sense others can gain from my answer too. You can not deny that my solution _is_ a swap. You can not deny that the question was how to swap in Java. My answer _is_ *a* solution to the question. Surprised that I have friends who agree with me? – nicerobot Sep 09 '15 at 19:22
  • 2
    No, its not. Not quite. You have not shown how to set the original x and y to their swapped values. It *would* be an answer, if you added the lines of code `x = yx[0]` and `y = yx[1]`. This would show the full complexity of your solution, in the context of the original question. Then readers could judge whether this was any simpler than simply copying and pasting the 3 lines inside OP's question, directly inline in their code. (Its not; it is more complex.) Or they could judge whether they had a situation that was different enough than OP, such that it was relevant. – ToolmakerSteve Sep 09 '15 at 19:26
  • Re "Surprised that I have friends who agree with me?" As I said, my amusement was about your gaining BOTH +1s within a 10 minute interval after 5 years, when someone questioned the utility of your answer. :) – ToolmakerSteve Sep 09 '15 at 19:29
  • @ToolmakerSteve Please vote however you see fit. Thanks for at least commenting about your reason. That's more than others have done on my rare down-votes. – nicerobot Sep 09 '15 at 19:32
  • @ToolmakerSteve So, your #comment52835966_2394633 is actually exactly the comment with which you should have lead. That is, how you think my answer can be improved. I actually completely agree with you. I was thinking about the answer in the array sense but that doesn't complete the thought for the answer. – nicerobot Sep 09 '15 at 20:18
1

Try this magic

public static <T> void swap(T a, T b) {
    try {
        Field[] fields = a.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object temp = field.get(a);
            field.set(a, field.get(b));
            field.set(b, temp);
        }
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

And test it!

    System.out.println("a:" + a);
    System.out.println("b:" + b);
    swap(a,b);
    System.out.println("a:" + a);
    System.out.println("b:" + b);
Mark Hetherington
  • 1,612
  • 14
  • 24
0

For integer types, you can do

a ^= b;
b ^= a;
a ^= b;

using the bit-wise xor operator ^. As all the other suggestions, you probably shouldn't use it in production code.

For a reason I don't know, the single line version a ^= b ^= a ^= b doesn't work (maybe my Java compiler has a bug). The single line worked in C with all compilers I tried. However, two-line versions work:

a ^= b ^= a;
b ^= a;

as well as

b ^= a;
a ^= b ^= a;

A proof that it works: Let a₀ and b₀ be the initial values for a and b. After the first line, a is a₁ = a₀ xor b₀; after the second line, b is b₁ = b₀ xor a₁ = b₀ xor (a₀ xor b₀) = a₀. After the third line, a is a₂ = a₁ xor b₁ = a₁ xor (b₀ xor a₁) = b₀.

Quirin F. Schroll
  • 1,302
  • 1
  • 11
  • 25