【问题标题】:In Java, remove empty elements from a list of Strings在 Java 中,从字符串列表中删除空元素
【发布时间】:2011-07-28 02:25:42
【问题描述】:

在 Java 中,我有一个字符串数组列表,例如:

[,Hi, ,How,are,you]

我想去掉null和empty元素,怎么改成这样:

[Hi,How,are,you]

【问题讨论】:

    标签: java arrays


    【解决方案1】:
    List<String> list = new ArrayList<String>(Arrays.asList("", "Hi", null, "How"));
    System.out.println(list);
    list.removeAll(Arrays.asList("", null));
    System.out.println(list);
    

    输出:

    [, Hi, null, How]
    [Hi, How]
    

    【讨论】:

    • java.util.AbstractList.remove()给我UnsupportedOperationException...
    • 该死的我已经重新做了它并且它有效。我的错。真诚的。
    • 我们需要从utilawt库中导入吗?
    • 有没有办法将列表转换回数组?我们可以在数组中保持与以前相同数量的位置吗?它只会将所有空白空间移到最后?
    • @LakshyaGoyal 他们说 Google 是你的朋友 - google.com/search?q=arraylist+to+array
    【解决方案2】:

    这是一个很晚的答案,但您也可以使用Collections.singleton

    List<String> list = new ArrayList<String>(Arrays.asList("", "Hi", null, "How"));
    list.removeAll(Collections.singleton(null));
    list.removeAll(Collections.singleton(""));
    

    【讨论】:

    • 它给出了 UnsupportedOperationException,不确定它对其他人如何工作
    • @Derick 如果您不使用新的 ArrayList 包装 Arrays.asList,那么它会给出 UnsupportedOperationException。因为 Arrays.asList 无法进行结构修改,所以无法进行 removeIf 操作。
    【解决方案3】:

    现在我们有了 Java 8 lambda 表达式的另一种方法。

    arrayList.removeIf(item -> item == null || "".equals(item));
    

    【讨论】:

    • 使用 Guava 你可以做到arrayList.removeIf(Strings::isNullOrEmpty);.
    • 或使用 Apache Commons arrayList.removeIf(StringUtils::isEmpty);
    • 或者如果你想删除除了空白字符之外的条目arrayList.removeIf(StringUtils::isBlank);
    • 顺便说一句,一旦你检查空值,使用 yoda 比较是没有意义的。
    • Java 11:arrayList.removeIf(String::isBlank);
    【解决方案4】:
    1. 如果您询问如何删除空字符串,您可以这样做(其中lArrayList&lt;String&gt;) - 这会删除所有null 引用和长度字符串0:

      Iterator<String> i = l.iterator();
      while (i.hasNext())
      {
          String s = i.next();
          if (s == null || s.isEmpty())
          {
              i.remove();
          }
      }
      
    2. 不要将ArrayList 与数组混淆,ArrayList 是一种动态数据结构,可根据其内容调整大小。如果你使用上面的代码,你不需要做任何事情来得到你描述的结果——如果你的 ArrayList 是 ["","Hi","","How","are" ,"you"], 如上所述删除后,它将正是您所需要的 - ["Hi","How","are","you"].

      但是,如果您必须拥有原始列表的“净化”副本(同时保持原样)并通过 '将其存储回来'你的意思是'制作一个副本',那么krmby在另一个答案中的代码会很好地为你服务。

    【讨论】:

    • 你提到的 arratlist 上没有 没有零参数的神奇删除方法
    • 请仔细查看 - remove() 是在 Iterator 而不是 ArrayList 上调用的
    • 来自 ypur 的回答 如果你在 ArrayList 上调用了 remove()
    • 如果您只想删除所有空字符串,您可以调用 remove("")。不过,这不适用于只有空格的字符串。
    • @krmby 已编辑,谢谢。 @squaknull 整洁,没有想到这一点(尽管您仍然必须循环执行)。这取决于 OP 的“空”是什么意思——我已经放入了一个免责声明,表明这个循环将删除所有 null 和空字符串。
    【解决方案5】:

    如果您使用的是 Java 8,请尝试使用 lambda 表达式和 org.apache.commons.lang.StringUtils,这也将清除 array 输入中的 nullblank

    public static String[] cleanArray(String[] array) {
        return Arrays.stream(array).filter(x -> !StringUtils.isBlank(x)).toArray(String[]::new);
    }
    

    参考-https://stackoverflow.com/a/41935895/9696526

    【讨论】:

    • 过滤器中的 Lambda 也可以替换为方法参考:filter(StringUtils::isNotBlank)
    【解决方案6】:

    您可以使用几种方法:

    1. 遍历列表,为要删除的列表元素调用Iterator.remove()。这是最简单的。

    2. 反复拨打List.remove(Object)。这也很简单,但性能最差……因为您反复扫描整个列表。 (但是,这可能是其迭代器不支持 remove 的可变列表的一个选项...由于某种原因。)

    3. 创建一个新列表,遍历旧列表,将要保留的元素添加到新列表中。

    4. 如果无法返回新列表,如上3.然后清除旧列表并使用addAll将新列表的元素添加回它。

    哪一个最快取决于原始列表的类、其大小以及需要删除的元素数量。以下是一些因素:

    • 对于ArrayList,每个单独的remove 操作为O(N),其中N 是列表大小。使用Iterator.remove() 方法(或ArrayList.remove(element) 方法)从大型ArrayList 中删除多个元素的成本很高。

      相比之下,LinkedListIterator.remove 方法是 O(1)

    • 对于ArrayList,创建和复制一个列表是O(N)相对便宜,特别是如果你可以确保目标列表的容量足够大(但不是太大)。

      相比之下,创建和复制到LinkedList 也是O(N),但要贵得多。

    所有这些加起来就是一个相当复杂的决策树。如果列表很小(比如 10 个或更少的元素),您可能可以使用上述任何方法。如果列表可能很大,您需要权衡列表中的所有问题,包括预期的列表大小和预期的移除数量。 (否则你可能会得到二次性能。)

    【讨论】:

      【解决方案7】:

      要把这个小金块放在这里:

      Stream.of("", "Hi", null, "How", "are", "you")
        .filter(t -> !Strings.isNullOrEmpty(t))
        .collect(ImmutableList.toImmutableList());
      

      我衷心希望 Java 有一个 filterNot

      【讨论】:

      • 什么是字符串 - 是番石榴吗?
      • @JWoodchuck 是的,我相信。
      • 我回答这个问题已经有一段时间了,但看起来是番石榴。
      【解决方案8】:
      • 这段代码可以顺利编译和运行。
      • 它不使用迭代器,因此更具可读性。
      • 列表是您的收藏。
      • 结果是过滤形式(不为空不为空)。

      public static void listRemove() {
          List<String> list = Arrays.asList("", "Hi", "", "How", "are", "you");
          List<String> result = new ArrayList<String>();
      
          for (String str : list) {
              if (str != null && !str.isEmpty()) {
                  result.add(str);
              }
          }
      
          System.out.println(result);
      }
      

      【讨论】:

      • 这会抛出一个java.lang.NullPointerException,因为str 可能是null
      【解决方案9】:

      如果您使用上述答案之一得到UnsupportedOperationException,并且您的List 是从Arrays.asList() 创建的,那是因为您无法编辑此类List

      要修复,请将Arrays.asList() 包裹在new LinkedList&lt;String&gt;() 中:

          List<String> list = new LinkedList<String>(Arrays.asList(split));
      

      来源来自这个answer

      【讨论】:

        【解决方案10】:

        关于 Andrew Mairose 的评论 - 虽然是一个很好的解决方案,但我想补充一点,此解决方案不适用于 固定大小 列表。

        您可以尝试这样做:

        Arrays.asList(new String[]{"a", "b", null, "c", "    "})
            .removeIf(item -> item == null || "".equals(item));
        

        但是你会遇到一个UnsupportedOperationException at java.util.AbstractList.remove(因为asList 返回一个不可调整大小的列表)。

        一个不同的解决方案可能是这样的:

        List<String> collect =
            Stream.of(new String[]{"a", "b", "c", null, ""})
                .filter(item -> item != null && !"".equals(item))
                .collect(Collectors.toList());
        

        这将产生一个很好的字符串列表:-)

        【讨论】:

        • 好点,但 OP 确实说它是ArrayList,它不是固定大小。
        【解决方案11】:
           private List cleanInputs(String[] inputArray) {
                List<String> result = new ArrayList<String>(inputArray.length);
                for (String input : inputArray) {
                    if (input != null) {
                        String str = input.trim();
                        if (!str.isEmpty()) {
                            result.add(str);
                        }
                    }
                }
                return result;
            }
        

        【讨论】:

          【解决方案12】:
          List<String> list = new ArrayList<String>(Arrays.asList("", "Hi", "", "How"));
                     Stream<String> stream = list .stream();
                     Predicate<String> empty = empt->(empt.equals(""));
                      Predicate<String> emptyRev = empty.negate();
                     list=  stream.filter(emptyRev).collect(Collectors.toList());
          

          list =  list .stream().filter(empty->(!empty.equals(""))).collect(Collectors.toList());
          

          【讨论】:

            【解决方案13】:

            lukastymo 的回答似乎是最好的。

            但由于它的可扩展性,这种方法也值得一提:

            List<String> list = new ArrayList<String>(Arrays.asList("", "Hi", null, "How", "are"));
            
            list = list.stream()
                       .filter(item -> item != null && !item.isEmpty())
                       .collect(Collectors.toList());
            
            System.out.println(list);
            

            我的意思是你可以添加额外的过滤器,例如:

                      .filter(item -> !item.startsWith("a"))
            

            ...虽然这当然与问题无关。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-20
              • 2014-02-18
              • 2020-04-05
              • 2011-12-02
              • 1970-01-01
              相关资源
              最近更新 更多