Java函数将字符串数组转换为列表,然后返回旧的字符串数组而不会丢失更改

时间:2014-06-11 05:54:13

标签: java arrays list

编辑:规则是我无法修改公式。方法必须是无效的,我必须将预初始化的数组传递给那些方法。这些是未来作业本身的限制因素,这就是为什么我试图以这种方式玩这个名字包计划。

我正在尝试编写一个“名称包”程序,以便为将来的作业带来乐趣和练习。目标是让用户有一个包。在这个包里,他们可以存储25个名字。他们可以一次添加1个名称,一次删除1个名称,对包进行排序以使名称按字母顺序排列等。基本数组练习。我遇到了一些问题,因为我对Java不是很熟悉。我有一个函数,它接受数组,将其转换为列表,尝试添加用户选择的名称,然后尝试将该列表转换回它曾经的数组。然后我有另一个函数试图显示数组中的所有内容。

当我避免使用菜单,开关盒和方法时,此代码可以正常工作。我可以将东西存储到名称包中,我可以毫无问题地显示名称,而不显示空值。但我不明白为什么名称不会显示在下面的代码中。有没有办法在Java中获得一种pass-by-reference效果?有没有更好的方法来做这种程序?我很感激任何建议!

这是我的代码:

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Arrays;

public class nameBag {
    public static void main(String[] args) {

        String[] nameBag = new String[25];
        Scanner input = new Scanner(System.in);

        while (true){

            System.out.println("Welcome to the bag of names.");
            System.out.println("1. Add an item to the bag.");
            System.out.println("2. Display items in bag.");
            System.out.println("0. Exit program.");

            int userChoice = input.nextInt();
            switch (userChoice){
                    case 1:
                    addName(nameBag);
                    break;
                case 2:
                    displayNames(nameBag);
                    break;
                case 0:
                    System.out.println("See ya!");
                    System.exit(0);
            }
        }
    }

    public static void addName(String[] nameBag){
        ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
        Scanner input = new Scanner(System.in);
        System.out.println("What name do you want to add to the pack?");
        String userSelection;
        userSelection = input.nextLine();
        nameList.add(userSelection);
        nameBag = nameList.toArray(nameBag);
    }

    public static void displayNames(String[] nameBag){
        for (String s : nameBag) {
            if (!(s == null)) {
                System.out.println(s);
            }
        }
    }
}

6 个答案:

答案 0 :(得分:1)

在处理之前检查输入是否为int类型,或者在处理输入之前执行所需的异常处理。

使用扫描程序hasNextInt()验证输入是否为int。

Scanner input = new Scanner(System.in);
while (!input.hasNextInt()) {
   System.out.println("Please enter int values only");
   input.nextLine();
} 

如果没有提供int,你也可以做一些异常处理以抛出异常

try {
        Scanner input = new Scanner(System.in);
        int userChoice = input.nextInt();
    } catch (Exception e) {
        System.out.println("Please re-enter");
    }

转换为数组

Arrays.asList(string.toCharArray());

如果你想将作为字符串数组

ArrayList<String> myList = new ArrayList<String>();
myList.add("value1");
myList .add("value2");
String[] myStringArray = new String[myList.size()];
myStringArray = myList.toArray(myStringArray);

答案 1 :(得分:0)

Java始终按值传递,因此没有按引用传递,但在大多数情况下,您的值是对对象的引用。

例如,如果向传递给方法的List添加元素,则可以在调用方法中看到该元素,因为传递给该方法的值实际上是对列表的引用。

您遇到的问题是此方法:

public static void addName(String[] nameBag){
    ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
    Scanner input = new Scanner(System.in);
    System.out.println("What name do you want to add to the pack?");
    String userSelection;
    userSelection = input.nextLine();
    nameList.add(userSelection);
    nameBag = nameList.toArray(nameBag);
}

你在主方法中使用名为nameBag的数组,这是引用(1)。

你调用你的addName(nameBag(1))(我将在括号中标记对象的引用)

然后你会做第一行

ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag(1)));

仍然使用相同的名字包。然后使用ArrayList做很多事情,这完全没问题 但是现在你做了

nameBag = nameList.toArray(nameList); //I assume a typo here

你的nameBag将成为nameBag(2),因为你会将另一个数组引用放入同一个变量中,所以从这一刻起你的方法中没有对nameBag(1)的引用。停止这种编程错误的最简单方法是将方法参数声明为final。

你可以用nameBag做的是你可以为索引分配一个值,这样如果你确实在调用者中看到了nameBag [1] =“foo”,但你无法重新赋值,因为你正在研究一个完全不同的物体。

你可以做的是要么不使用数组而不是使用List但是如果这是一个数组练习,只需返回你在最后一行创建的nameBag并在main方法中重新设置数组

答案 2 :(得分:0)

试试这段代码效果很好。你犯了几个错误,这就是它无法正常工作的原因。我已将您的代码保留为注释,理解起来会很方便。

记住这一点。这将有助于我希望: 1.尝试使用List或Set而不是Arrays,因为Arrays不是动态大小 2.默认情况下,树集将对内容进行排序 3.当不需要时,不要将值传递给方法

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;

public class nameBag {
static Set<String> nameBagSet = new TreeSet<String>();
public static void main(String[] args) {

    //String[] nameBag = new String[25];

    Scanner input = new Scanner(System.in);

    while (true){

        System.out.println("Welcome to the bag of names.");
        System.out.println("1. Add an item to the bag.");
        System.out.println("2. Display items in bag.");
        System.out.println("0. Exit program.");

        int userChoice = input.nextInt();
        switch (userChoice){
                case 1:
                addName();
                break;
            case 2:
                displayNames();
                break;
            case 0:
                System.out.println("See ya!");
                System.exit(0);
        }
    }



}

public static void addName(){
//    ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));

Scanner input = new Scanner(System.in);
System.out.println("What name do you want to add to the pack?");
String userSelection;
userSelection = input.nextLine();
nameBagSet.add(userSelection);
//    nameList.add(userSelection);
//    nameBag = nameList.toArray(nameBag);
 }

 public static void displayNames(){
 for (String s : nameBagSet) {
    if (!(s == null)) {
        System.out.println(s);
    }
}

} }

答案 3 :(得分:0)

addName方法中的以下行在实际执行中没有任何影响。      nameBag = nameList.toArray(nameBag);

原因是,你真的在​​改变你的本地变量&#34; nameBag&#34;指向一个新的数组。这对主函数中定义的变量没有影响。

要真正了解正在发生的事情,请将addName的变量名称更改为其他名称。对于例如paramNameBag。您将立即了解正在发生的事情。当您进行这样的更改时,您希望上面的行实际上是指main方法中定义的变量。但是你不能在这里访问它,因为它是main方法的本地方法。由于您使用的是所有静态方法,因此唯一可以实现的方法是将nameBag声明移出并使其静止。

还有另一种快速而肮脏的解决方案。将addName签名更改为下面,并从该方法返回该数组。然后,您可以将返回的数组重新分配给主变量。

 public static String[] addName(String[] nameBag, String userSelection){
    .....
    .....
    return nameList.toArray(nameBag);
 }



    switch (userChoice){
                case 1:
                namesBag = addName(nameBag);

这应该这样做。

但我真的建议首先使用ArrayList而不是数组,然后来回转换为ArrayList。

祝你好运

答案 4 :(得分:0)

没有进入良好的编码约定,你的程序中有两个错误

1st displayNames(nameBag 

您似乎已在编辑中更正了

和第二个错误与理解java中的参数有关。您不能将nameBag作为参数传递,并将值添加到这些参数。每次函数addName()结束执行时,这些值都会丢失。您可以在类变量下声明静态变量nameBag并直接操作它,而不是将其作为参数传递。这样,即使addName()displayName()函数结束执行(只要程序正在运行),您的更改也会反映出来。另外,你不需要任何退货类型。您可以直接访问全局List变量。

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Arrays;

public class HelloWorld{

static String[] nameBag; // NameBag is declared as class variable

static{

    nameBag = new String[25]; //initialize nameBag

}

    public static void main(String[] args) {


        Scanner input = new Scanner(System.in);

        while (true){

            System.out.println("Welcome to the bag of names.");
            System.out.println("1. Add an item to the bag.");
            System.out.println("2. Display items in bag.");
            System.out.println("3. Exit program.");
              int userChoice=0;
             try{
           userChoice = input.nextInt();
             }
             catch(Exception e){
                 e.printStackTrace();

             }
            switch (userChoice){
                    case 1:
                    addName(); //No need to pass nameBag as a parameter
                    break;
                case 2:
                    displayNames(); //No need to pass nameBag as a parameter
                    break;
                case 3:
                    System.out.println("See ya!");
                    System.exit(0);
            }
        }



    }

public static void addName(){
    //everything is same here, just accessing nameBag directly
    Scanner input = new Scanner(System.in);
    System.out.println("What name do you want to add to the pack?");
    String userSelection;
    userSelection = input.nextLine();
    ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(nameBag));
    nameList.add(userSelection);
    nameBag = nameList.toArray(nameBag);
}

public static void displayNames(){
//everything is same here, just accessing nameBag directly
    for (String s : nameBag) {
        if (!(s == null)) {
            System.out.println(s);
        }
    }
}
}

答案 5 :(得分:0)

没有通过引用发送基于类的对象的简单方法,所有类都以这样的方式传递,即对它们的引用作为复制为值的参数传递。

为了避免这种情况,你可以使用一个持有指针的Holder对象,那个作为引用发送的是指向Holder对象的指针,但是它内部的对象实际上是指向你想要的对象的指针。操纵。

所以而不是:

public class nameBag 
{
    public static void main(String[] args) 
    {
       String[] nameBag = new String[25];

你会:

public class ArrayHolder
{
    private String[] nameBag;

    public ArrayHolder(String[] nameBag)
    {
        this.setNameBag(nameBag); 
    }

    public String[] getNameBag()
    {
        return this.nameBag;
    }

    public void setNameBag(String[] nameBag)
    {
        this.nameBag = nameBag;
    }
    //by the way, if these functions break your limitations,
    //then it works even if nameBag is just a simple public variable
}

然后你可以:

public class nameBag 
{
    public static void main(String[] args) 
    {
       String[] nameBag = new String[25];
       ArrayHolder arrayHolder = new ArrayHolder(nameBag);
       ...

但是你必须将ArrayHolder发送到你的函数:

public static void addName(ArrayHolder arrayHolder)
{
    //everything is same here, just accessing nameBag directly
    Scanner input = new Scanner(System.in);
    System.out.println("What name do you want to add to the pack?");
    String userSelection = input.nextLine();
    ArrayList<String> nameList = new ArrayList<String>(Arrays.asList(arrayHolder.getNameBag()));
    nameList.add(userSelection);
    nameBag = nameList.toArray(new String[nameList.size()]);
}

但正如您最初所说,Array必须是参数,它不能是您自己的ArrayHolder对象;在这个前提下,我想唯一的解决方案就是你需要把它变成一个静态变量。