Hỏi về truyền mảng vào phương thức trong java

Em có đoạn code như thế này
Em muốn thêm con n vào vị trí pos trong mảng a. Trong main em gọi hàm xuất ra thì không thay đổi cho em hỏi code em sai chỗ nào.
hàm này nằm chung với class chứa main.

public static void addElement(int a[],int pos,int n)
	{
		// 1 2 3 4 5
		// 1 2 3 6 4 5
		// tao 1 mang b có kích thước là n+1
		int b[] = new int [a.length+1];
		// chuyen gia tri sang mang b
		for(int i = 0 ; i < a.length ; i ++)
			b[i] = a[i];
		
		for(int i = b.length-1 ; i > pos ; i--)
			b[i] = b[i-1];
		b[pos] = n;
		// delete mang a
		a = new int [b.length];
		for(int i = 0 ; i < b.length; i++)
			a[i] = b[i];
	}

java nó khác C/C++ nha bạn, mình chưa test, nhưng mà mình nghĩ là tại vì ở hàm main khi bạn truyền mảng vào phương thức, thì tại đây nó sẽ tạo 1 mảng mới và gán các giá trị của mảng bạn định truyền vào.

Tức là tại đây thay vì nó lấy cái mảng bạn muốn chỉnh sửa thì nó lại tạo 1 mảng mới y chang cái mảng của bạn. Hai cái mảng này giống nhau ngoại trừ cái tham chiếu của nó thì khác nhau thôi, giống như bạn có 2 con trỏ trong C/C++, mỗi con trỏ nó lại trỏ đến 1 cái mảng khác nhau dù rằng 2 cái mảng này có giá trị bằng nhau.

Nên trong phương thức của bạn, cái mảng bạn chỉnh sửa không có dính dáng gì đến cái mảng bên ngoài hàm main cả, cái mảng trong phương thức bạn đã sửa đổi, nhưng ở ngoài thì vẫn còn y nguyên.

3 Likes

Cần gì làm thế. Chỉ cần:

a=b;

Thay vì trả về void thì nên trả về int[]
Khi đó có thể gán trở lại a sau khi thêm.

public static int[] addElement(int a[],int pos,int n){
//...
    return b;
}

// main
    int[] a=...
    a=addElement(a,3,6);
1 Like

a = b Mình mới biết cái này chắc giống con trỏ bên C. Mình đã test thử và code chạy thành công, nhưng có 1 thắc mắc là khi mình truyền mảng vào không có cách nào thay đổi trực tiếp thay vì phải trả về.

Đối với C# thì có từ khóa ref cho phép thay đổi giá trị con trỏ. Java thì không.
Tuy nhiên có 1 cách là dùng đối tượng chứa mảng.

public class Main{

public static class ArrayContainer{
    public int[] a;
    public ArrayContainer(int[] _a){
        a=_a;
    }
}

    public static void addElement(ArrayContainer ac, int pos, int v){
        int[] b = new int[ac.a.length+1];
        for(int i=0;i<pos;i++){
            b[i]=ac.a[i];
        }
        b[pos]=v;
        for(int i=pos+1;i<b.length;i++){
            b[i]=ac.a[i-1];
        }
        ac.a=b;
    }
    public static void main(String... args){
        ArrayContainer x = new ArrayContainer(new int[]{1,2,3,4,5});
        addElement(x,3,6);
        for(int i = 0; i<x.a.length;i++){
            System.out.println(x.a[i]);
        }
    }
}
2 Likes
class Quicksort{
	static void qsort(char item[])
	{
		qs(item, 0 , item.length-1);
	}
	private static void qs(char item[],int left,int right )
	{
		// ham quick sort
		..
		..
	}
}
class QSDemo
{
	public static void main(String[] args)
	{
		char a[] = {'d','x','a','r','p','j','i'};
		Quicksort.qsort(a);
	}
}

Mình có đoạn code như thế này, bỏ vào phương thức thì nó thay đổi được mảng.

Ở đây bạn truyền vào một biến cục bộ, nên ở đây sẽ là Pass by Vaule, tức là nó chỉ nhận giá trị của mảng chứ không phải là con trỏ chỉ đến mảng.


Có 2 cách để bạn giải quyết việc này :wink:

  • Sử dụng biến toàn cục để chuyển qua thành Pass by Reference . Nhưng ở đây vì bạn viết ở 2 Class khác nhau nên sẽ khác là phức tạp đấy, chuyển sang cách 2 sẽ nhanh hơn :smile:
  • Để void qsort trả về char[] đã sắp xếp :wink:
class Quicksort{
	static char[] qsort(char item[])
	{
		return qs(item, 0 , item.length-1);
	}
	private static char[] qs(char item[],int left,int right )
	{
		// ham quick sort
		..
		..
        // return ...
	}
}
class QSDemo
{
	public static void main(String[] args)
	{
		char a[] = {'d','x','a','r','p','j','i'};
        a = Quicksort.qsort(a);		
	}
}
3 Likes
import java.util.*;

public class test
{
	public static void  bubbleSort(int a[])
	{
		for(int i = a.length-1; i >= 0 ;i --)
			for(int j = 0 ; j < i ; j ++)
				if(a[j] > a[j+1]) 
				{
					int temp = a[j];
					a[j] = a[j+1];
					a[j+1] = temp;
				}
	}
	public static void addElement(int a[],int pos,int n)
	{
		int b[] = new int [a.length+1];
		
		for(int i = 0 ; i < a.length ; i++)
			b[i] = a[i];

		for(int i = b.length-1; i> pos ; i--)
			b[i] = b[i-1];
 		
		b[pos] = n;
		
		a = new int [b.length];

		for(int i = 0 ; i < b.length; i++)
			a[i] = b[i];	
	}
	public static void main(String args[])
	{
		Scanner scanner = new Scanner(System.in);
		System.out.println("Nhap n ");	
		int n = scanner.nextInt();

		int [] a = new int [n];		
		for(int i = 0 ; i < n ; i++)
		{
			System.out.println("Moi ban nhap gia tri "+i);
			a[i] = scanner.nextInt();
		}
		// sort ham 
		bubbleSort(a);
		// xuat mang
		addElement(a,0,450);
		System.out.println();
		for(int i= 0 ; i < a.length ; i ++)
		System.out.print(a[i]+" ");
		scanner.close();
	}
}

Mình sẽ giải thích chương trình mình trước thì sau khi nhập giá trị xong, mình sẽ sắp xếp bằng method bubbleSort() => chương trình chạy và sắp xếp được. Tuy nhiên với addElement method => chương trình không hoạt động và in ra kêt quả như bình thường. Vậy thì nguyên nhân là do gì?

Mình nói ở trên rồi mà =_= Bạn đang truyền vào mảng a là một biến cục bộ chứ không phải biến toàn cục, vậy nên nó sẽ là Pass by Vaule chứ không phải là Pass by Reference. Vì vậy mà bạn thay đổi giá trị ở trong các void thì giá trị ở mảng a vẫn sẽ không thay đổi :smile:

1 Like

Nhưng bubbleSort method của mình lại thay đổi và sắp xếp tăng dần được ý?

đảo giá trị phần tử chứ đâu phải tạo mới (new int[]). Khác đấy.

  • Thay đổi vị trí các phần tử nghĩa là con trỏ vào mảng vẫn giữ nguyên.
  • Tạo mới là cấp vùng nhớ mới và thao tác trên vùng nhớ mới, con trỏ với giá trị mới. Không liên quan gì đến vùng nhớ trước đó.
4 Likes

ơ bạn ôi chắc lúc a = new int[b.length] thì nó khởi tạo mảng a mới r. cái mảng cũ của b vẫn giữ nguyên sao á

Cảm ơn hướng dẫn của cậu nhé!
Cậu ấy biết từ 4 năm trước rồi cậu ơi :smile:

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?