64

I have an array of objects in Java, and I am trying to pull one element to the top and shift the rest down by one.

Assume I have an array of size 10, and I am trying to pull the fifth element. The fifth element goes into position 0 and all elements from 0 to 5 will be shifted down by one.

This algorithm does not properly shift the elements:

Object temp = pool[position];

for (int i = 0; i < position; i++) {                
    array[i+1] = array[i];
}
array[0] = temp;

How do I do it correctly?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
darksky
  • 20,411
  • 61
  • 165
  • 254
  • 1
    As @PaulSassik says, if you need to shift, then this is not a good use of an array. Either use a linked list, or use some kind of pointer into the buffer (and yes, you can have something that approximates a pointer in java). – Marcin Nov 01 '11 at 18:20
  • 4
    Consider using `System.arraycopy()`. – greybeard Jan 16 '16 at 17:42
  • https://stackoverflow.com/questions/59713753/need-some-help-to-demystify-system-arraycopy – Rajat Jan 13 '20 at 10:49

16 Answers16

102

Logically it does not work and you should reverse your loop:

for (int i = position-1; i >= 0; i--) {                
    array[i+1] = array[i];
}

Alternatively you can use

System.arraycopy(array, 0, array, 1, position);
Howard
  • 38,639
  • 9
  • 64
  • 83
  • Don't forget to create a new array larger than the original. `String[] newArray = new String[myArray.length +1]; System.arraycopy(myArray, 0, newArray, 1, myArray.length);` – Hugo Gresse Sep 09 '15 at 13:07
  • 1
    If performance is an issue, my tests suggest that it's very much faster to overwrite the original array than to use System.arraycopy(). Initialising new arrays seems to be quite expensive. – Tullochgorum Feb 12 '18 at 20:13
  • 1
    @Hugo Gresse you don't need to create a temporary copy of the array. See the manual page for arraycopy. – rghome Dec 31 '18 at 13:06
  • 2
    @Tullochgorum System.arraycopy can shift elements and you should not create a new copy of the array. The manual says "If the src and dest arguments refer to the same array object, then the copying is performed *as if* the components at positions srcPos through srcPos+length-1 were first copied to a temporary array...", the key words in that sentence being "as if". – rghome Dec 31 '18 at 13:06
32

Assuming your array is {10,20,30,40,50,60,70,80,90,100}

What your loop does is:

Iteration 1: array[1] = array[0]; {10,10,30,40,50,60,70,80,90,100}

Iteration 2: array[2] = array[1]; {10,10,10,40,50,60,70,80,90,100}

What you should be doing is

Object temp = pool[position];

for (int i = (position - 1); i >= 0; i--) {                
    array[i+1] = array[i];
}

array[0] = temp;
Komal Padia
  • 1,686
  • 1
  • 11
  • 4
29

You can just use Collections.rotate(List<?> list, int distance)

Use Arrays.asList(array) to convert to List

more info at: https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#rotate(java.util.List,%20int)

Murat Mustafin
  • 1,284
  • 10
  • 17
5

Just for completeness: Stream solution since Java 8.

final String[] shiftedArray = Arrays.stream(array)
        .skip(1)
        .toArray(String[]::new);

I think I sticked with the System.arraycopy() in your situtation. But the best long-term solution might be to convert everything to Immutable Collections (Guava, Vavr), as long as those collections are short-lived.

Benjamin Marwell
  • 1,173
  • 1
  • 13
  • 36
5

Instead of shifting by one position you can make this function more general using module like this.

int[] original = { 1, 2, 3, 4, 5, 6 };
int[] reordered = new int[original.length];
int shift = 1;

for(int i=0; i<original.length;i++)
     reordered[i] = original[(shift+i)%original.length];
lukaspp
  • 1,059
  • 10
  • 15
2

Manipulating arrays in this way is error prone, as you've discovered. A better option may be to use a LinkedList in your situation. With a linked list, and all Java collections, array management is handled internally so you don't have to worry about moving elements around. With a LinkedList you just call remove and then addLast and the you're done.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
  • Yes I know - I chose an Array for some other reasons even though I know its not the best option. – darksky Nov 01 '11 at 18:21
  • 1
    There are many collections to choose from, including generic collections. If you share with us why you needed to use a plain array perhaps we can offer some other alternative suggestions. – Paul Sasik Nov 01 '11 at 18:22
1

Using array Copy Generic solution for k times shift k=1 or k=3 etc

public void rotate(int[] nums, int k) {
            //  Step 1
            // k > array length then we dont need to shift k times because when we shift
            // array length times then the array will go back to intial position.
            // so we can just do only k%array length times.
            // change k = k% array.length;
    
            if (k > nums.length) {
                k = k % nums.length;
            }
            
            //   Step 2;
            // initialize temporary array with same length of input array.
            // copy items from input array starting from array length -k as source till
            // array end and place in new array starting from index 0;
            int[] tempArray = new int[nums.length];
    
            System.arraycopy(nums, nums.length - k, tempArray, 0, k);
            
            //   step3:
            // loop and copy all the remaining elements till array length -k index and copy
            // in result array starting from position k
            for (int i = 0; i < nums.length - k; i++) {
                tempArray[k + i] = nums[i];
            }
            
            // step 4 copy temp array to input array since our goal is to change input
            // array.
    
            System.arraycopy(tempArray, 0, nums, 0, tempArray.length);
    
        }

code

 public void rotate(int[] nums, int k) {
                if (k > nums.length) {
                    k = k % nums.length;
                }
                int[] tempArray = new int[nums.length];
                System.arraycopy(nums, nums.length - k, tempArray, 0, k);
                for (int i = 0; i < nums.length - k; i++) {
                    tempArray[k + i] = nums[i];
                }
                System.arraycopy(tempArray, 0, nums, 0, tempArray.length);
            }
Lijo
  • 6,498
  • 5
  • 49
  • 60
1

Try this:

Object temp = pool[position];

for (int i = position-1; i >= 0; i--) {                
    array[i+1] = array[i];
}

array[0] = temp;

Look here to see it working: http://www.ideone.com/5JfAg

thejh
  • 44,854
  • 16
  • 96
  • 107
  • @Nayefc: You first copy element 0 to 1. Then you copy the *new* element 1 to 2. And so on. So basically, apart from index 0, everything has the same value afterwards. – thejh Nov 01 '11 at 18:19
0
static void pushZerosToEnd(int arr[])
    {   int n = arr.length;
        int count = 0;  // Count of non-zero elements
        // Traverse the array. If element encountered is non-zero, then
        // replace the element at index 'count' with this element
        for (int i = 0; i < n; i++){
            if (arr[i] != 0)`enter code here`
               // arr[count++] = arr[i]; // here count is incremented
                swapNumbers(arr,count++,i);
        }
        for (int j = 0; j < n; j++){
            System.out.print(arr[j]+",");
        }
     }

    public static void swapNumbers(int [] arr, int pos1, int pos2){
        int temp  = arr[pos2];
        arr[pos2] = arr[pos1];
        arr[pos1] = temp;
    }
expert
  • 1
0

Another variation if you have the array data as a Java-List

    listOfStuff.add( 
            0, 
            listOfStuff.remove(listOfStuff.size() - 1) );

Just sharing another option I ran across for this, but I think the answer from @Murat Mustafin is the way to go with a list

Community
  • 1
  • 1
Gene Bo
  • 11,284
  • 8
  • 90
  • 137
0
public class Test1 {

    public static void main(String[] args) {

        int[] x = { 1, 2, 3, 4, 5, 6 };
        Test1 test = new Test1();
        x = test.shiftArray(x, 2);
        for (int i = 0; i < x.length; i++) {
            System.out.print(x[i] + " ");
        }
    }

    public int[] pushFirstElementToLast(int[] x, int position) {
        int temp = x[0];
        for (int i = 0; i < x.length - 1; i++) {
            x[i] = x[i + 1];
        }
        x[x.length - 1] = temp;
        return x;
    }

    public int[] shiftArray(int[] x, int position) {
        for (int i = position - 1; i >= 0; i--) {
            x = pushFirstElementToLast(x, position);
        }
        return x;
    }
}
Taegost
  • 1,208
  • 1
  • 17
  • 26
  • 1
    You should probably explain your code a bit, also, I don't think this is going to work. Your method pushFirstElementToLast accepts the parameter position, but then doesn't do anything with it... Plus the name of the method suggests that it just moves the first element to the end, instead of inserting it in a specific position. – Taegost Jan 23 '18 at 13:55
  • position variable in that method was unneeded, I accept, but if my code doesn't solve the original problem, plz provide me with the input and the expected output, I will be more than happy to work on it – Alok Pathak Jan 24 '18 at 19:24
0

A left rotation operation on an array of size n shifts each of the array's elements unit to the left, check this out!!!!!!

public class Solution {
    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        String[] nd = scanner.nextLine().split(" ");

        int n = Integer.parseInt(nd[0]);  //no. of elements in the array

        int d = Integer.parseInt(nd[1]);  //number of left rotations

        int[] a = new int[n]; 

      for(int i=0;i<n;i++){
          a[i]=scanner.nextInt();
      }

        Solution s= new Solution();     
//number of left rotations
        for(int j=0;j<d;j++){
              s.rotate(a,n);
        }
   //print the shifted array  
        for(int i:a){System.out.print(i+" ");}
    }

//shift each elements to the left by one 
   public static void rotate(int a[],int n){
            int  temp=a[0];
        for(int i=0;i<n;i++){
            if(i<n-1){a[i]=a[i+1];}
            else{a[i]=temp;}
      }}
}
malith vitha
  • 473
  • 4
  • 4
0

You can use the Below codes for shifting not rotating:

    int []arr = {1,2,3,4,5,6,7,8,9,10,11,12};
            int n = arr.length;
            int d = 3;

Programm for shifting array of size n by d elements towards left:

    Input : {1,2,3,4,5,6,7,8,9,10,11,12}
    Output: {4,5,6,7,8,9,10,11,12,10,11,12}

        public void shiftLeft(int []arr,int d,int n) {
            for(int i=0;i<n-d;i++) {
                arr[i] = arr[i+d];
            }
        }

Programm for shifting array of size n by d elements towards right:

    Input : {1,2,3,4,5,6,7,8,9,10,11,12}
    Output: {1,2,3,1,2,3,4,5,6,7,8,9}

        public void shiftRight(int []arr,int d,int n) {

            for(int i=n-1;i>=d;i--) {
                arr[i] = arr[i-d];
            }
        }
double-beep
  • 5,031
  • 17
  • 33
  • 41
0

In the first iteration of your loop, you overwrite the value in array[1]. You should go through the indicies in the reverse order.

BenH
  • 2,100
  • 2
  • 22
  • 33
-1

Write a Java program to create an array of 20 integers, and then implement the process of shifting the array to right for two elements.

public class NewClass3 {
    
     public static void main (String args[]){
     
     int a [] = {1,2,};
    
     int temp ;
     
     for(int i = 0; i<a.length -1; i++){
      
         temp = a[i];
         a[i] = a[i+1];
         a[i+1] = temp;
     
     }
     
     for(int p : a)
     System.out.print(p);
     }
    
}
lczapski
  • 4,026
  • 3
  • 16
  • 32
-1
import java.util.Scanner;

public class Shift {

    public static void main(String[] args) {

        Scanner input = new Scanner (System.in);
        int array[] = new int [5];
        int array1[] = new int [5];
        int i, temp;

        for (i=0; i<5; i++) {
            System.out.printf("Enter array[%d]: \n", i);
            array[i] = input.nextInt(); //Taking input in the array
        }

        System.out.println("\nEntered datas are: \n");
        for (i=0; i<5; i++) {
            System.out.printf("array[%d] = %d\n", i, array[i]); //This will show the data you entered (Not the shifting one)
        }

        temp = array[4]; //We declared the variable "temp" and put the last number of the array there...

        System.out.println("\nAfter Shifting: \n");

        for(i=3; i>=0; i--) {
            array1[i+1] = array[i]; //New array is "array1" & Old array is "array". When array[4] then the value of array[3] will be assigned in it and this goes on..
            array1[0] = temp; //Finally the value of last array which was assigned in temp goes to the first of the new array
        }


        for (i=0; i<5; i++) {
            System.out.printf("array[%d] = %d\n", i, array1[i]);
        }

        input.close();

    }

}