【问题标题】:How can I double the size of the array without getting NullPointException?如何在不获取 NullPointErexception 的情况下将数组的大小加倍?
【发布时间】:2018-10-06 22:26:03
【问题描述】:

首先,为了快速了解一下,这是我昨天的帖子:

How to work around a NullPointerException in Java?

所以我得到了这个 NullPointerException,我现在相信它发生在我尝试在字符串数组中找到第一个副本的索引之前。在搜索第一个副本的索引之前,我使用此方法将字符串数组的大小加倍:

static String[] upSizeArr( String[] fullArr )
{

    int size = fullArr.length; 
    String[] newSizeArr = new String[(2 * size)]; 
    for (int a = 0; a < size; a++) {
        newSizeArr[a] = fullArr[a];
    }
    return newSizeArr;
}

然后我在这个 while 循环的上下文中使用该方法:

static final int CAPACITY = 10;
int wordCount = 0;

BufferedReader wordFile = new BufferedReader( new FileReader(args[1]) );
String[] wordList = new String[CAPACITY];

while ( wordFile.ready() ) 
    {   if ( wordCount == wordList.length ) 
            wordList = upSizeArr( wordList );
        wordList[wordCount++] = wordFile.readLine();
    } 
wordFile.close();

是否可以使用 upSizeArr 方法解决此问题?我希望解决方案是基本的,并且只使用没有其他数据结构的数组。我是编程新手,我真的很想掌握基础知识……大约一周左右一直在寻找解决这个 NullPointException 的方法。

这是完整的代码:

import java.io.*;
import java.util.*;
public class Practice
{
    static final int CAPACITY = 10;
    static final int NOT_FOUND = -1;
    public static void main (String[] args) throws Exception
    {
        if (args.length < 1 )
        {
            System.out.println("\nusage: C:\\> java Practice <words filename>\n\n"); // i.e. C:\> java Lab2 10Kints.txt 172822words.txt
            System.exit(0);
        }


    String[] wordList = new String[CAPACITY];
    int wordCount = 0;
    BufferedReader wordFile = new BufferedReader( new FileReader(args[0]) );

    while ( wordFile.ready() ) // i.e. while there is another line (word) in the file
    {   if ( wordCount == wordList.length ) 
            wordList = upSizeArr( wordList );
        wordList[wordCount++] = wordFile.readLine();
    } //END WHILE wordFile
    wordFile.close(); 
    System.out.format( "%s loaded into word array. size=%d, count=%d\n",args[0],wordList.length,wordCount );
    int dupeIndex = indexOfFirstDupe( wordList, wordCount );
    if ( dupeIndex == NOT_FOUND )
        System.out.format("No duplicate values found in wordList\n");
    else
        System.out.format("First duplicate value in wordList found at index %d\n",dupeIndex);

} // END OF MAIN

// TWO METHODS 

static String[] upSizeArr( String[] fullArr )
{

    int size = fullArr.length; //find the length of the arrays
    String[] newSizeArr = new String[(2 * size)]; // creates new array, doubled in size
    for (int a = 0; a < size; a++) {
        newSizeArr[a] = fullArr[a];
    }
    return newSizeArr;

}
static int indexOfFirstDupe( String[] arr, int count )
{       
    Arrays.sort(arr);
    int size = arr.length;
    int index = NOT_FOUND;

    for (int x = 0; x < size; x++) {
        for (int y = x + 1; y < size; y++) {
            if (arr[x].equals(arr[y])) {
                index = x;
                break;
            }
        }
    }
    return index;
    }
} // END OF PROGRAM

另外,用作参数的文件是一个 txt 字符串文件。

【问题讨论】:

  • 我没有看到您提供的任何会取消引用 null 的代码。你能提供更多的上下文/代码吗?异常到底是在哪里抛出的?在您链接到的原始帖子中,异常是由于数组的一半(调整大小后的“新”一半)包含nulls,Arrays.sort 将抛出一个尝试比较nulls 的异常。这可以通过创建一个处理null 的比较器来解决,如下所示:stackoverflow.com/questions/14514467/…
  • 我推荐ArrayListSystem.arraycopy
  • wordFile.ready() 没有做你认为的事情
  • 哪一行实际抛出异常?
  • 所以我对您的代码进行了非常快速的破解,没有尝试读取文件,并且它不会生成 NPE。我怀疑wordFile.ready()wordList[wordCount++] = wordFile.readLine() 的组合会将null 值放入数组中(wordFile.readLine() 将在到达文件末尾时返回null)。

标签: java arrays nullpointerexception


【解决方案1】:

我不确定这是否是您的问题的原因,但它非常可疑......

while ( wordFile.ready() ) {
    //...
}

不是您应该阅读文件的方式。相反,您应该检查readLine 的返回结果,它会在到达文件末尾时返回null

也许更像......

try (BufferedReader wordFile = new BufferedReader(new FileReader(args[1]))) {
    String[] wordList = new String[CAPACITY];

    String text = null;
    while ((text = wordFile.readLine()) != null) {
        if (wordCount == wordList.length) {
            wordList = upSizeArr(wordList);
        }
        wordList[wordCount++] = text;
    }
} catch (IOException ex) {
    ex.printStackTrace();
}

您的代码还存在使文件资源处于打开状态的风险。上面的例子使用了try-with-resources 语句来确保它被正确关闭,无论操作是否成功。

查看The try-with-resources Statement了解更多详情。

除非有特殊要求,否则我还建议使用 ArrayListSystem.arraycopy 来代替像这样滚动您自己的解决方案。

或许可以查看List Implementations 了解更多详情

从可运行示例更新...

在没有可运行代码示例的情况下,当upSizeArr 创建一个新数组时,它会将新元素默认为null,这是意料之中的,我很惊讶Arrays.sort 无法处理这个。

“A”解决方案是用不同的非默认值填充未使用的空间...

static String[] upSizeArr(String[] fullArr) {

    int size = fullArr.length; //find the length of the arrays
    String[] newSizeArr = new String[(2 * size)]; // creates new array, doubled in size
    for (int a = 0; a < size; a++) {
        newSizeArr[a] = fullArr[a];
    }
    for (int a = size; a < newSizeArr.length; a++) {
        newSizeArr[a] = "";
    }
    return newSizeArr;

}

“另一种”解决方案可能是“缩小”数组以适应可用数据...

static String[] downsizeToCapacity(String[] fullArr) {
    int lastIndex = 0;
    while (lastIndex < fullArr.length && fullArr[lastIndex] != null) {
        lastIndex++;
    }
    if (lastIndex >= fullArr.length) {
        return fullArr;
    }
    String[] downSized = new String[lastIndex];
    System.arraycopy(fullArr, 0, downSized, 0, lastIndex);

    return downSized;
}

所有这一切都试图创建一个新数组,其大小仅足以包含所有非空值并将其返回。

然后你可以使用类似...

System.out.format("%s loaded into word array. size=%d, count=%d\n", "words.txt", wordList.length, wordCount);
wordList = downsizeToCapacity(wordList);
System.out.format("%s loaded into word array. size=%d, count=%d\n", "words.txt", wordList.length, wordCount);

int dupeIndex = indexOfFirstDupe(wordList, wordCount);

在我的测试中,输出

words.txt loaded into word array. size=160, count=99
words.txt loaded into word array. size=99, count=99
No duplicate values found in wordList

【讨论】:

  • 您好,感谢您的帮助!不幸的是,数组是一个特定的要求,我需要根据教授的要求使用 Arrays.sort() 。无论如何我可以重写方法而不是while(wordFile()),因为那是我不允许修改的代码?我的任务只是制作方法。我试着把 Arrays.sort(arr, Comparator.nullsLast(Comparator.naturalOrder()));将空值放在数组的后面,程序继续运行......我取得进展了吗?非常感谢您的帮助!
  • "while(wordFile()),因为那是我不允许修改的代码?" ... ? ... 但这是错误的代码并且可能是您问题的根源。我已经测试了数组调整大小,它似乎对我来说很好,虽然我可能会使用 arraycopy 来代替
  • 呃,对不起那个人!无论如何我可以重写我的方法,以便代码至少可以运行?我也尝试了arraycopy方式:(我的教授不是在寻找效率或复杂的代码(因为他自己似乎没有最“高效”的代码xD)
  • 检查null 值并将它们默认为非null
  • 好的,所以我在原始帖子中的 upSizeArr 方法和 indexOfFirstDupe 方法看起来都不错?我试过: String[]cleanArray = Arrays.stream(arr).filter(Objects::nonNull).toArray(String[]::new);清理 arr 数组,但现在我的程序无法完成运行......
猜你喜欢
  • 2014-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多