我上高中并参加了AP计算机编程课程(Java)。在我的课程中,我必须创建一个void
方法来对传入的数组进行排序。它必须是void
(要求)并且需要修改传递给它的变量(要求)。我必须使用他们提供的跑步者代码。我对编码很新,但仍然对语言可以做什么和不能做什么感到困惑。排序有效,但我看不到如何修改main
方法的传入变量。
public class InsertionSort extends Sort {
public <T extends Comparable<T>> void sortList(ArrayList<T> arr) {
ArrayList<T> arr2 = new ArrayList<T>(arr.size());
for (int i = 0; i < arr.size(); i++) {
boolean done = false;
int insertIndex = 0;
int k = i;
T next = arr.get(i);
while (k>0 && insertIndex == 0) {
if (next.compareTo(arr2.get(k-1)) > 0) {
// System.out.println("if i" + i + " k" + k);
insertIndex = k;
done = true;
}
k--;
}
arr2.add(insertIndex, arr.get(i));
}
//System.arraycopy(arr2,0,arr,0,arr2.size());
arr = arr2; //<--my attempt to alter runner variable
//System.out.println(" arr 2 = " + arr2);
//System.out.println(" arr 1 = " + arr);
}
}
// Runner
public static void main( String[] args )
{
ArrayList<String> s = new ArrayList<String>();
String[] sArr = { "you", "can", "observe", "a", "lot", "just", "by", "watching" };
for ( String x : sArr ) { s.add( x ); }
Sort ss = new InsertionSort();
ss.sortList( s );
System.out.println( s );
}
我基本上需要在调用ArrayList
方法(已排序)时修改sortList()
(s),然后从对System.out.println()
的调用打印。
排序有效,但“s”不会改变,我不知道从哪里开始修复它。调用者完全一成不变(类要求),类和方法标题必须保持不变(出于同样的原因)。
我可能会在副本和粘贴中遗漏“{”或“}”。
答案 0 :(得分:2)
您可以修改ArrayList arr
的内容。首先,清空内容。然后添加第二个List
中的元素。像
// arr = arr2; // <--my attempt to alter runner variable
arr.clear(); // <-- empty arr
arr.addAll(arr2); // <-- copy arr2 contents to arr.
List.clear()
说(部分)
此调用返回后列表将为空。
将指定集合中的所有元素按指定集合的迭代器(可选操作)返回的顺序追加到此列表的末尾。
最后,您无法使用List
修改调用方对arr = arr2;
传入的引用,因为(即使Java始终按值传递),{的值也是{ {1}}是它的&#39; 参考
答案 1 :(得分:1)
您需要直接对arr
列表进行排序,您无法将此类列表指定为java is pass by value。但是,您仍然可以实现此目的,因为传递的对象仍然可以访问引用:
public <T extends Comparable<T>> void sortList(ArrayList<T> arr) {
ArrayList<T> arr2 = new ArrayList<T>(arr);
for (int i = 0; i < arr2.size(); i++) {
boolean done = false;
int insertIndex = 0;
int k = i;
T next = arr2.get(i);
while (k > 0 && insertIndex == 0) {
if (next.compareTo(arr2.get(k - 1)) > 0) {
insertIndex = k;
done = true;
}
k--;
}
arr.set(insertIndex, arr2.get(i));
}
}
我在算法中修改的内容:
arr2
现在是arr
的临时列表克隆。arr2
并在arr2
而不是arr
上进行验证。arr
。然后你的程序将输出
[a, can, observe, a, by, just, by, watching]
而不是
[you, can, observe, a, lot, just, by, watching]
答案 2 :(得分:1)
这与变量传递到方法的方式有关,Java有两种方法可以根据输入类型执行此操作。第一种是传递值,并在传递基元时使用。按值传递意味着将基本类型中保存的实际值复制到新的内存位置,然后该位置可供被调用方法使用。例如,int值0xDEADBEEF会将0xDEADBEEF的位模式复制到新位置,并将其传递给被调用的方法。
Java中的其他所有(非原始)都是一个对象(Object的实例),对象通过引用值传递。基本上所有持有对象的变量实际上都是引擎盖下的指针(它们是一个变量,它保存实际对象的基本内存位置,从堆中分配,而不是保持对象本身)。将对象值传递给方法时,不会复制对象,而是复制保存对象基址的变量。这意味着对该变量的任何操作都将引用(指向)调用方法所持有的原始对象。这也意味着如果重新分配“指向”对象的变量,则会丢失对该对象的引用,并且无法将其取回。
IE:
public static void doSomething(LinkedList<String> strings, int num) {
if (strings == null)
return;
// here we modify the content of strings
strings.add("NEW STRING!");
// now the calling method can see the change, the list size
// increased by 1 to anything that holds a reference to this list
// here we lose our reference to strings
strings = new LinkedList<String>();
// we can no longer make changes to strings that the calling
// method will see because we no longer have a reference to
// the original list!
// here we save, then change num
int oldNum = num;
num = Integer.MAX_VALUE;
// the calling method has no way to know that num has changed.
// it still thinks num = oldNum
}
希望这有助于澄清!
答案 3 :(得分:0)
而不是像在此处一样创建新数组
ArrayList<T> arr2 = new ArrayList<T>(arr.size());
在你的情况下只需编辑你得到的数组作为函数参数,你得到参数作为参数,这意味着你直接编辑对象
public void sortList( ArrayList<T> arr )
我建议你在这里使用修饰符final,这样你就无法真正改变它所指向的对象。
public void sortList(final ArrayList<T> arr )
答案 4 :(得分:0)
sortList
内创建arr
的副本:
ArrayList<T> arrCopy = new ArrayList<T>(arr);
清除arr后
arr.clear();
将代码arr
替换为arrCopy
。
将代码arr2
替换为arr
。
答案 5 :(得分:-1)
Java使用引用语义。因此,您可以将“arr”参数视为指向数组的指针。记住它只是一个指针,所以你可以逐个将arr2的内容复制到arr1,它应该可以正常工作。
代替: arr = arr2
尝试:
for (int i=0; i<arr.size(); ++i) {
arr[i] = arr2[i];
}