【问题标题】:Best way to remove null values from string array从字符串数组中删除空值的最佳方法
【发布时间】:2015-07-23 09:35:46
【问题描述】:

以下是删除空值的两种方法,哪一种是最好的方法?

public static String[] clean(final String[] v) {
    List<String> list = new ArrayList<String>(Arrays.asList(v));
    list.removeAll(Collections.singleton(null));
    return list.toArray(new String[list.size()]);
}

public static String[] clean(final String[] v) {
    List<String> list = new ArrayList<String>(v.length);
     for (String aString : v)
        {
            if (aString != null)
            {
                list.add(aString);
            }
        }
    return list.toArray(new String[list.size()]);
}

【问题讨论】:

  • 两者的最终结果相同。 “更好”是什么意思?处理时间?内存使用情况?可读性?
  • 我会让 List 类处理它。即使用第一个。不过,两者看起来都是对性能的巨大浪费。
  • 研究你的建议,真正的问题是How to remove null elements from a list。我链接到的问题建议了您的第一种方法。
  • 您还可以做一些 Java 8 技巧。同样,这取决于您认为哪种方法比另一种方法更好。
  • 在第二个例子中,为什么你初始化你的listv 一样大小?这不会删除您的 null 值,还是我错过了什么?

标签: java arrays string


【解决方案1】:

为了从单个字符串中删除空值,我会使用这样的正则表达式,

private static Pattern pattern = Pattern.compile("(?i)[(\\[{]?null[)\\]}]?");

    public static String removeNullString(String value) {
        if (StringUtils.isEmpty(value)) {
            return StringUtils.EMPTY;
        }

        Matcher matcher = pattern.matcher(value);
        return matcher.replaceAll(StringUtils.EMPTY);
    }

它覆盖了字符串中的所有“null”和空字符。

用于在 Java 7 中从字符串数组中删除空值

String[] firstArray = {"test1", "", "test2", "test4", "", null};

    List<String> list = new ArrayList<String>();

    for(String s : firstArray) {
       if(s != null && s.length() > 0) {
          list.add(s);
       }
    }

    firstArray = list.toArray(new String[list.size()]);

用于在 Java 8 中从字符串数组中删除空值

String[] firstArray = {"test1", "", "test2", "test4", "", null};

firstArray = Arrays.stream(firstArray)
                     .filter(s -> (s != null && s.length() > 0))
                     .toArray(String[]::new); 

【讨论】:

  • 这不是从 String 中删除 null,而是从 String[] 中删除。您的解决方案不适用
  • 我认为 .filter(Objects::nonNull) 比您当前的过滤器更干净。
  • 您的解决方案会过滤掉空字符串 ("")。但是,原始问题中从未提出过这个问题。
【解决方案2】:

在性能方面,通常最好尽量减少当前代码块(即方法)范围之外的调用。此外,由于与大多数其他指令相比,内存分配相对较慢,因此避免对象创建通常是一个目标。在性能方面我能想到的最好的(我选择让它足够灵活以接受任何类型的数组):

public <T> T[] removeNulls(Class<T> type, final T[] original){

    // first, shift all non-null instances to the head, all nulls to the end.
    int nonNullCount=0;
    T tempT = null;

    for(int i=0; i < original.length; i++){
        if(original[i] != null){
            nonNullCount++;
        }else if(i != original.length - 1){
            // Swap the next non-null value with this null value
            int j = i + 1;
            // In case there are multiple null values in a row
            // scan ahead until we find the next non-null value
            while(j < original.length && (tempT = original[j]) == null){
                j++;
            }
            original[nonNullCount] = tempT;
            if(tempT != null){
                nonNullCount++;
            }
            if(j < original.length){
                original[j] = null;
            }

            i = j - 1;
        }
    }

    // The case where there are no nulls in the array
    if(nonNullCount == original.length){
        return original;
    }

    final T[] noNulls = (T[]) Array.newInstance(type,nonNullCount);
    System.arraycopy(original,0,noNulls,0,nonNullCount);
    return  noNulls;
}

但我不确定为什么在性能不太可能成为问题的情况下,您为什么希望这种复杂性超过 3 或 4 行来做同样的事情。您需要拥有巨大的数组才能看到我的代码和您的干净示例之间的任何好处(如果有的话)。

【讨论】:

    【解决方案3】:

    在 Java 8 中,您应该能够执行以下操作:

    List<String> list = new ArrayList<String>(Arrays.asList(v));
    list.removeIf(Objects::isNull);
    return list.toArray(new String[list.size()]);
    

    【讨论】:

    • 但在本例中,首先您必须将数组转换为 collection,然后再将其转换为数组
    【解决方案4】:

    如果您想在同一个空间进行操作,我会建议以下解决方案。但最终数组也将具有相同的大小。我的意思是它的大小不会缩小,但所有元素都会以相同的顺序聚合。

       public static void removeNullFromArray(String[] args) {
          int location = 0;
          for(int i=0;  i<args.length; i++){
             String arg = args[i];
             if(arg!=null){
                if(location<i){
                   args[location] = arg;
                   args[i] = null;
                }
                location++;
             }
          }
       }
    

    【讨论】:

      【解决方案5】:

      使用流和 lambda 的 Java 8 代码。从数组中过滤非空值并转换为列表。

      Arrays.stream(arr).filter(Objects::nonNull).collect(Collectors.toList());
      

      【讨论】:

        猜你喜欢
        • 2016-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        • 2015-11-11
        • 2016-10-30
        • 2021-05-21
        相关资源
        最近更新 更多