简体   繁体   中英

Strange behavior when copying an array Java in static method

I have a problem with creating a copy of an array in Java.

I pass a copy of the received data to my custom sort method. The problem is the original array changes too. I 've tried with .clone() and with some other methods which I found on the internet but the result always was the same: sorted array. I think it's specific for java behaviour and it's super easy to fix. Probably something with static keyword (?). Normally I'm programming in JS, Java is not for me:(

    public static void mySort(Example[] data) {
        Example[] copy = Arrays.copyOf(data, data.length);
        Example[] sortedArray= customSort(copy);
        System.out.println("Original data (should not be sorted): ");
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }

How to create a true copy of the received data in mySort method?

All code:

package com.company;

import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

public class Main {

    public static void main(String[] args) {

        Example examples[] = new Example[20];

        for (int i = 0; i < examples.length; i++) {
            int randomValue1 = ThreadLocalRandom.current().nextInt(1, 6);
            double randomValue2 = ThreadLocalRandom.current().nextDouble();
            examples[i] = new Example(randomValue1, randomValue2);
        }

        System.out.println("Beforesort: ");
        for (int i = 0; i < examples.length; i++) {
            System.out.println(i + ". " + examples[i]);
        }

        mySort(examples);
    }

    public static void mySort(Example[] data) {
        Example[] copy = Arrays.copyOf(data, data.length);
        Example[] sortedArray= customSort(copy);
        System.out.println("Original data (should not be sorted): ");
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }

// you can ignore this, it's just customSort
    static Example[] customSort(Example[] copy) {

        for (int i = 0; i < copy.length; i++) {
            for (int j = 0; j < copy.length - i - 1; j++)
                if (copy[j].value1 != copy[j + 1].value1) {
                    if (copy[j].value1 > copy[j + 1].value1) {
                        int temp = copy[j].value1;
                        copy[j].value1 = copy[j + 1].value1;
                        copy[j + 1].value1 = temp;
                    }
                } else {
                    if (copy[j].value2 > copy[j + 1].value2) {
                        double temp = copy[j].value2;
                        copy[j].value2 = copy[j + 1].value2;
                        copy[j + 1].value2 = temp;
                    }
                }


        }
        return copy;
    }

}

class Example {
    int value1;
    double value2;

    public Example(int value1, double value2) {
        this.value1 = value1;
        this.value2 = value2;
    }

    @Override
    public String toString() {
        return "Example{" +
                "value1=" + value1 +
                ", value2=" + value2 +
                '}';
    }
}

The issue is that you are sorting by swapping the content of the Example instances. Imagine those instances with the corresponding values (just in an abstract way):

e1 = 3;
e2 = 1;
e3 = 2;

You are swapping the values , not the positions of the instances.

e1 = 1;
e2 = 2;
e3 = 3;

You can see that the values are sorted, but this hasn't affected the position of instances. Every array that references those instances will obviously see those changes as the values are changed, not the position in the sort array.

What you need is:

e2 = 1;
e3 = 2;
e1 = 3;

As you can see, the order itself is changed, not whatever an instance contains. This will obviously only be visible in the one array, the one you swap the instances in.

Your sorting function has to be like so:

    static Example[] customSort(Example[] copy) {

        for (int i = 0; i < copy.length; i++) {
            for (int j = 0; j < copy.length - i - 1; j++)
                if (copy[j].value1 != copy[j + 1].value1) {
                    if (copy[j].value1 > copy[j + 1].value1) {
                        Example temp = copy[j];
                        copy[j] = copy[j + 1];
                        copy[j + 1] = temp;
                    }
                } else {
                    if (copy[j].value2 > copy[j + 1].value2) {
                        Example temp = copy[j];
                        copy[j] = copy[j + 1];
                        copy[j + 1] = temp;
                    }
                }


        }
        return copy;
    }

Again, your current version swaps values not positions . I hope that's clear now.


Here's the whole thing:

import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

public class Main {

    public static void main(String[] args) {

        Example examples[] = new Example[20];

        for (int i = 0; i < examples.length; i++) {
            int randomValue1 = ThreadLocalRandom.current().nextInt(1, 6);
            double randomValue2 = ThreadLocalRandom.current().nextDouble();
            examples[i] = new Example(randomValue1, randomValue2);
        }

        System.out.println("Beforesort: ");
        for (int i = 0; i < examples.length; i++) {
            System.out.println(i + ". " + examples[i]);
        }

        mySort(examples);
    }

    public static void mySort(Example[] data) {
        Example[] copy = Arrays.copyOf(data, data.length);
        Example[] sortedArray= customSort(copy);
        System.out.println("Original data (should not be sorted): ");
        for (int i = 0; i < data.length; i++) {
            System.out.println(i + ". " + data[i]);
        }

        System.out.println("Sorted data: ");
        for (int i = 0; i < sortedArray.length; i++) {
            System.out.println(i + ". " + sortedArray[i]);
        }
    }

// you can ignore this, it's just customSort
    static Example[] customSort(Example[] copy) {

        for (int i = 0; i < copy.length; i++) {
            for (int j = 0; j < copy.length - i - 1; j++)
                if (copy[j].value1 != copy[j + 1].value1) {
                    if (copy[j].value1 > copy[j + 1].value1) {
                        Example temp = copy[j];
                        copy[j] = copy[j + 1];
                        copy[j + 1] = temp;
                    }
                } else {
                    if (copy[j].value2 > copy[j + 1].value2) {
                        Example temp = copy[j];
                        copy[j] = copy[j + 1];
                        copy[j + 1] = temp;
                    }
                }


        }
        return copy;
    }

}

class Example {
    int value1;
    double value2;

    public Example(int value1, double value2) {
        this.value1 = value1;
        this.value2 = value2;
    }

    @Override
    public String toString() {
        return "Example{" +
                "value1=" + value1 +
                ", value2=" + value2 +
                '}';
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM