【问题标题】:Java - ArrayList not detecting duplicate valueJava - ArrayList 未检测到重复值
【发布时间】:2014-09-20 15:51:20
【问题描述】:

我为我的程序编写了以下类:

public class RefGen {

    private static String refNo;

    protected static void generate(){

         //Create array to store reference
         ArrayList<String> refList = new ArrayList<>();

         //Get date and set output format
         DateFormat dateFormat = new SimpleDateFormat("yyMMdd");        
         Date curDate = new Date();

          //Variables
          String clientKey = InGenUI.clientText.getText();
          String refDate = dateFormat.format(curDate); 
          String refType = InGenUI.typeCombo.getSelectedItem().toString();
          String userName = InGenUI.userCombo.getSelectedItem().toString();
          String ref;
          int n = 1;

          //Create Reference
          refNo = clientKey.toUpperCase() + "/" + refDate + "/" + refType + "/" + userName + "/" + Integer.toString(n);

          //Check to see if refNo already exists in array
          while (refList.contains(refNo)) {
              n = n + 1;
              refNo = clientKey.toUpperCase() + "/" + refDate + "/" + refType + "/" + userName + "/" + Integer.toString(n);
              refList.add(refNo);
          }

          refList.add(refNo);
          System.out.println(refList);
      }

      public static String reference(){

          return refNo;
      }
  }

这个类的目的是生成一个唯一的参考号并将其存储在一个数组中。在这样做之前,它需要检查数组是否已经包含该值。如果不是,则 n 加 1,直到 refNo 成为数组中不存在的唯一值。

RefGen.reference() 由 InGenUI.java 中的 genButton 调用,将 refNo 的值输出到 clientLabel em> 也在 InGenUI.java 中:

    private void genButtonActionPerformed(java.awt.event.ActionEvent evt) {                                          
        RefGen.generate();
        String refNo = RefGen.reference();
        clientLabel.setText(refNo);
    }

程序生成引用编号,但从不增加 InGenUI.java 中的标签值或 RefGen.java 中的实际数组本身。似乎该数组在每次按钮单击时只保存一个值。

我认为 refList 存储生成的原始 refNo 值,但每次这样做时都会清空数组。我怀疑每次单击 genButton 我实际上是在创建一个新的 refList 实例,因此会清除旧值。它是否正确?如果是这样,我如何保护我创建的 refList 实例,同时将其保存在 RefGen.java 类中?

提前谢谢你。

【问题讨论】:

  • 我认为你应该使用 HashSet 而不是 ArrayList。
  • 我同意@Stefan Beike 的观点。我不知道您的 ArrayList 的实际大小,但如果它足够大,那么检查它是否包含每个元素会产生很大的不同。

标签: java arrays arraylist contains


【解决方案1】:

每次调用generate 时,您似乎都在创建一个新的数组列表:

     //Create array to store reference
     ArrayList<String> refList = new ArrayList<>();

您应该在类级别的方法之外声明它。

【讨论】:

    【解决方案2】:

    好吧,您可以将 refList 设为类变量,即将其移出 generate() 方法。

    我不知道您对“保护列表”的确切含义,但您可以将列表设为私有/受保护成员,并且只允许通过特殊方法进行操作。

    此外,我不确定这部分是否按预期工作(无论是当前还是在建议的更改之后):

    while (refList.contains(refNo)) {
              n = n + 1;
              refNo = clientKey.toUpperCase() + "/" + refDate + "/" + refType + "/" + userName + "/" + Integer.toString(n);
              refList.add(refNo); //<-- problems here
     }
    

    目前,您的列表不会包含refNo,因此不会被添加。
    在建议的更改之后,列表将包含refNo,但现在您将再次添加。因此,您可能希望删除该添加操作。

    正如已经建议的那样,您可能还想使用Set&lt;String&gt; 并选择适合您需求的实现,例如TreeSet&lt;String&gt; 的参考编号应该按 LinkedHashSet&lt;String&gt; 排序,如果(第一个)插入的顺序很重要。

    使用集合,您甚至可以不断重新添加元素(这仍然很奇怪,但您可以),因为集合不允许重复。

    您也可以更改代码以尝试添加参考编号,但如果没有成功或集合的大小没有改变,请增加编号并重试。

    更新:

    我没有意识到该方法是静态的(感谢 Stephen C),所以我将有关实例变量的部分移到了这里。

    通常静态变量在存储参考列表等数据时不太受欢迎。有多种原因,例如如果您想对多个列表、封装和继承使用相同的代码(例如,您不能覆盖静态方法并且让非静态方法写入静态变量通常没有真正意义),内存泄漏的可能性怎么办? (如果您不手动将静态设置为 null 或自己卸载类,则无法收集它们)等等。

    因此,您可能会考虑更改两种更改代码的可能性:

    • 将列表保留在类之外并将其作为参数传递
    • 更改代码以使列表和生成方法非静态。

    【讨论】:

    • 是的,除了 OP 在这里实际上使用了static 方法,所以“实例变量”需要是一个static 变量。
    • 谢谢大家,这很好用。我还注意到上面提到的问题是将程序发送到无限循环。注意到使用 Hash 来提高性能,但我会先完成程序并考虑在必要时进行更改。目前该列表将非常小,可能一天最多20​​个条目。再次感谢您的帮助。
    猜你喜欢
    • 2023-03-04
    • 2020-03-08
    • 1970-01-01
    • 2019-03-12
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多