当我将 ArrayList 的 get 方法传递给一个变量时,它使用的是整个 ArrayList

Posted

技术标签:

【中文标题】当我将 ArrayList 的 get 方法传递给一个变量时,它使用的是整个 ArrayList【英文标题】:When I pass an ArrayList's get method a variable, it's using the whole ArrayList 【发布时间】:2016-02-10 11:04:19 【问题描述】:

由于某种原因,当我传递我的 ArrayList(它是来自 Java 的 Lang.* 的基本 ArrayList)一个 int 变量时,而不是在变量 int 的索引处获取项目(例如: i = 0; arrayList.get(i); 应该是第一个ArrayList 中的项目) - 它调用 WHOLE 列表。

下面是有问题的方法:

public ZipCode findZip (int zip) 
    ZipCode aZip = new ZipCode(00000);
     //System.out.println(zips.get(0)); here gives 99501,ANCHORAGE,AK
     //System.out.println(zips.get(0).getZipCode()); here gives 99501
        for(int i = 0; i < zips.size(); i++) 
            if(zips.get(i).getZipCode() == zip)
                aZip = zips.get(i);
              //System.out.print(aZip); here gives the zip codes from the whole array
            else
                aZip = null;
        
    return aZip;
    //Therefore, aZip is ALWAYS null. Even if it exists.

我尝试了一系列故障排除来解决这个问题。到目前为止,我了解到当我输入一个直整数时不会出现问题(例如: arrayList.get(1); 正常获取第二项)。不幸的是,没有要显示的编译器错误。

它运行时总是给我 null 。 我需要使用一个 int 所以我可以增加它来遍历列表,这也很不幸。 更大的程序片段:(与我之前的问题相同)
import java.util.*;
import java.io.*;
import java.lang.Math;
public class ZipCodeDatabase 
   //Field
    private ArrayList<ZipCode> zips;

   //Constructor
   public ZipCodeDatabase () 
      zips = new ArrayList<ZipCode> (); 
   

   //Mutator Method
   public void readZipCodeData(String filename) 
      Scanner inFS = null; 
      FileInputStream fileByteStream = null;
      try
       // open the File and set delimiters
         fileByteStream = new FileInputStream(filename);
         inFS = new Scanner(fileByteStream);
         inFS.useDelimiter("[,\r\n]+");
       // continue while there is more data to read
         while(inFS.hasNext()) 
            //read in all input
            int aZip = inFS.nextInt();
            String aCity = inFS.next();
            String aState = inFS.next();
            double aLat = inFS.nextDouble();
            double aLon = inFS.nextDouble();
            //Create and add new zipcode
            ZipCode newZip = new ZipCode(aZip, aCity, aState, aLat, aLon);
            zips.add(newZip);
         
         fileByteStream.close();
         // Could not find file
         catch(FileNotFoundException error1) 
            System.out.println("Failed to read the data file: " + filename);
          // error while reading the file                      
         catch(IOException error2) 
             System.out.println("Oops! Error related to: " + filename);
              
   

   //Accessor Methods
   public ZipCode findZip (int zip) 
      ZipCode aZip = new ZipCode(00000);
      for(int i = 0; i < zips.size(); i++) 
          if(zips.get(i).getZipCode() == zip)
            aZip = zips.get(i);
         else
            aZip = null;
      
      return aZip;
   

这是 getZipCode() 方法(它返回邮政编码 int,是包含纬度和经度的一小部分 int 的一部分;我有一个数组):

public int getZipCode () 
       return zipCode;

【问题讨论】:

什么是zips?您能否展示一个重现问题的完整示例? 你为什么有else aZip = null?这更改aZip 以引用null,即使在循环的早期找到匹配项也是如此。我认为您根本不想要 else 声明。 向我们展示来自zips 和 ZipCode 类的代码。 getZipCode()的返回类型是什么? 你在哪里发布了getZipCode()方法? 【参考方案1】:

当您找到邮政编码时,您不会停止循环,因此您在循环中的下一次迭代通常会将您的返回值设置为 null。将您的声明更改为:

为您的教授编辑:

 ZipCode aZip = null;
 for(int i = 0; i < zips.size() && aZip == null; i++) 

    if(zips.get(i).getZipCode() == zip) 
            aZip = zips.get(i);
    
 
 if (aZip == null) 
    aZip = new ZipCode(00000);  
    // return new ZipCode(00000); would be better
 

 return aZip;

【讨论】:

我必须返回一个变量,教授对循环内的返回很生气。 然后在aZip = zips.get(i); 之后使用break 关键字。 break 表示不再循环,因为我已经得到了我想要的东西。 Is it bad style to use 'return' to break a for loop in Java? 您也可以将 break 隐式放入 for 语句声明中:for(int i = 0; i &lt; zips.size() &amp;&amp; aZip.getZipCode() == 0; i++) 。但在我的书中,从循环内部返回很好。 但是。这给了我一个想法。【参考方案2】:

由于您在找到匹配项后没有停止循环,因此下一次迭代的结果将覆盖您的匹配项,这很可能是一个不匹配项,因此用null 覆盖它。有几种选择:

break 出:

public ZipCode findZip (int zip) 
  ZipCode aZip = null;
  for(int i = 0; i < zips.size(); i++) 
      if(zips.get(i).getZipCode() == zip) 
        aZip = zips.get(i);
        break;
     
     else
        aZip = null;
  
  return aZip;

改变循环条件:

public ZipCode findZip (int zip) 
  ZipCode aZip = null;
  for(int i = 0; i < zips.size() && aZip==null; i++) 
      if(zips.get(i).getZipCode() == zip)
        aZip = zips.get(i);
     else
        aZip = null;
  
  return aZip;

不要覆盖:

public ZipCode findZip (int zip) 
  ZipCode aZip = null;
  for(int i = 0; i < zips.size(); i++) 
      if(zips.get(i).getZipCode() == zip)
        aZip = zips.get(i);
     else
        continue; // obsolete, but you said, your prof insist on it…
  
  return aZip;


最后一点,最干净的解决方案是在 ZipCode 类中提供正确的 equals 方法。如果ZipCode 类有正确的equals 实现,您可以简单地实现该方法:

public ZipCode findZip (int zip) 
  ZipCode aZip = new ZipCode(zip);
  if(zips.contains(aZip))
    return aZip;
  else
    return null;

或者,甚至更短:

public ZipCode findZip (int zip) 
  ZipCode aZip = new ZipCode(zip);
  return zips.contains(aZip)? aZip: null;

【讨论】:

【参考方案3】:

谢谢大家!

虽然其他答案确实有效,但这是一个不同的解决方案,它给出了似乎正确的答案:
public ZipCode findZip (int zip) 
      ZipCode aZip = null;
      for(int i = 0; i < zips.size(); i++) 
          if(zips.get(i).getZipCode() == zip) 
            aZip = zips.get(i);
          
      
      return aZip;
   

【讨论】:

这就是我的答案! :P Mine 已经过优化,因为它会在找到该项目时停止迭代。 当然可以。是 说 else 部分是你的教授要求的。 null 是,所以我不知道另一种说法【参考方案4】:

问题在于,当您找到目标 ZipCode 时,您并没有停止迭代,而是在后续迭代中将 null 分配给您的 aZip 变量。

要解决它,您可以使用条件来停止迭代:

ZipCode aZip = null;

for (int i = 0; (i < zips.size()) && (aZip == null); i++) 
    if (zips.get(i).getZipCode() == zip) 
        aZip = zips.get(i); // When you set this, aZip will no longer be == null
    

【讨论】:

以上是关于当我将 ArrayList 的 get 方法传递给一个变量时,它使用的是整个 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

当我将它传递给套接字 io 时,对象失去了它的原型功能

LUA:避免通过引用传递

如何将arraylist传递给onClick的方法

Ionic 2:当我将数组传递给组件时,我在 component.ts 上得到一个字符串

当我将 JSON 对象架构传递给客户端时,它看起来不同

将arraylist传递给另一个类以检查可用性及其过期日期的方法