繁体   English   中英

如何编写一个通用的isEmpty方法,可以检查null,为空?

[英]How to write a generic isEmpty method which can check for null, empty?

我正在编写一个实用程序方法,可以检查空字符串和空字符串,或集合或对象或任何常规类型 -

public static boolean isEmpty(Object obj) {
    if (obj == null)
        return true;
    if (obj instanceof Collection)
        return ((Collection<?>) obj).size() == 0;

    // is below line expensive?
    final String s = String.valueOf(obj).trim();

    return s.length() == 0 || s.equalsIgnoreCase("null");
}

如何使我的上述方法高效,因为上面的isEmpty方法将从应用程序中多次调用,这对性能至关重要?

我怀疑下面的行是昂贵的,因为繁重的toString方法,它会创建临时垃圾,可能会导致GC并降低性能?

final String s = String.valueOf(obj).trim();

更新: -

我现在为每种类型分离了isEmpty方法。 以下是我在简化上述isEmpty方法后得到的结果。

public static boolean isEmpty(Object obj) {
    if (obj == null) {
        return true;
    }
    return false;
}

public static boolean isEmpty(Collection<?> value) {
    if (value == null || value.isEmpty()) {
        return true;
    }
    return false;
}

public static boolean isEmpty(String value) {
    if (value == null || value.isEmpty()) {
        return true;
    }
    return false;
}

更新2: -

如果我需要检查map null或empty,我是否应该同时保存集合isEmpty和Map isEmpty方法,或者Collection isEmpty方法可以正常吗?

public static void main(String[] args) {

    Map<String, String> hello = new HashMap<String, String>();
    System.out.println(isEmpty(hello));

    Map<String, HashMap<Integer, String>> primary = new HashMap<String, HashMap<Integer, String>>();
    System.out.println(isEmpty(primary));

}

public static boolean isEmpty(Collection<?> value) {
    return value == null || value.isEmpty();
}

public static boolean isEmpty(Map<?, ?> value) {
    return value == null || value.isEmpty();
}

这听起来像是一个糟糕的设计。 Null为null,empty为空,如果是字符串,则为字符串,依此类推。 不要试图用一种方法堵塞一切。 这对于可维护性和可读性是不利的。

if (str == null || str.isEmpty())
    ...

if (coll == null || coll.isEmpty())

都很好。

然而,我个人尝试永远不会将null与空字符串或空集合等同。 我认为这是一个不好的做法。 一个null集是没有收藏可言,空集是实际上还是一个集合。 通过保持集合非空,可以避免许多if (coll == null)检查。 如果您担心内存消耗,请使用Collections.emptySet等。


话虽这么说,如果你仍然想要朝着这个方向前进,我建议你使用普通方法重载并创建一个isEmpty(Collection<?> coll)和一个isEmpty(String str)来避免instanceof和cast。


关于你的编辑:

不要这样做

if (value == null || value.isEmpty()) {
    return true;
}
return false;

做就是了

return value == null || value.isEmpty();

对于集合,您将需要使用isEmpty()而不是size() 对于某些集合类型(例如LinkedList),size()比isEmpty()更昂贵。

我喜欢在一个处理它的公共库中有一个实用程序类。 注意,如果对象有一个(在确定对象不为null之后),我们使用对象自己的isEmpty,length或size方法(按此顺序)。 通过拨打这个电话,人们不再需要担心NPE了 - 你打电话给这个并且你很有兴趣 - 如果它是真的,那么你的集合/ map / etc不是null有一些东西; 如果它是假的,则跳过该项目(它由null或自己的帐户为空)。 第二种方法检查数组以查看它是空还是空,但不检查内容。 迭代数组时,只需执行检查,然后迭代,并在迭代时检查每个元素。

/**
 * Provides methods to perform input validation and boundary validation.
 */
public final class ValidationUtils {
    /**
     * Check to see if Object is empty or null.
     *
     * @param object
     *            The object to check
     * @return boolean {@code true} iff the Object is null or determined to be empty (using methods that it provides --
     *         if it doesn't provide such methods, it's only empty if it's null)
     */
    public static boolean isEmpty(@Nullable final Object object) {
        if (object == null)
            return true;

        try {
            // Try to use the object class's isEmpty method to check if we're empty, now that we know we're
            // not NULL
            final Method method = object.getClass().getMethod("isEmpty");
            final Object result = method.invoke(object);

            if (result instanceof Boolean)
                return Boolean.class.cast(result).booleanValue();
        } catch (@NotNull final NoSuchMethodException | InvocationTargetException | IllegalArgumentException
                | IllegalAccessException | SecurityException ignored) {
            // We couldn't invoke... let's go to the next common method
        }

        try {
            // Try to use the object class's length method to check if we're empty, now that we know we're
            // not NULL
            final Method method = object.getClass().getMethod("length");
            final Object result = method.invoke(object);

            if (result instanceof Integer)
                return Integer.class.cast(result).intValue() <= 0;
            if (result instanceof Long)
                return Long.class.cast(result).longValue() <= 0L;
        } catch (@NotNull final NoSuchMethodException | InvocationTargetException | IllegalArgumentException
                | IllegalAccessException | SecurityException ignored) {
            // We couldn't invoke... let's go to the next common method
        }

        try {
            // Try to use the object class's size method to check if we're empty, now that we know we're
            // not NULL
            final Method method = object.getClass().getMethod("size");
            final Object result = method.invoke(object);

            if (result instanceof Integer)
                return Integer.class.cast(result).intValue() <= 0;
            if (result instanceof Long)
                return Long.class.cast(result).longValue() <= 0L;
        } catch (@NotNull final NoSuchMethodException | InvocationTargetException | IllegalArgumentException
                | IllegalAccessException | SecurityException ignored) {
            // We couldn't invoke... but we're not null... treat it like an Object
        }

        // Let's treat it like an Object... we're not null, so we're not empty
        return false;
    }

    /**
     * Check to see if the array of Objects is empty or null.
     *
     * @param obj
     *            Object Array to check
     * @return boolean true if empty
     */
    public static boolean isEmpty(@Nullable final Object... obj) {
        return ((obj == null) || (obj.length == 0));
    }
}

示例用途:

    final Map<String, String[]> postData = ServletActionContext.getRequest().getParameterMap();
    // We're testing if the map is null or empty... we could just do a null check here because of how we're using the map after, but...
    if (!ValidationUtils.isEmpty(postData)) {
        for (final Map.Entry<String, String[]> reqKey : postData.entrySet()) {
            // We're checking if the array is null or doesn't have any length; again, the foreach does the latter, but this is perfectly fine
            if (!ValidationUtils.isEmpty(reqKey.getValue())) {
                for (final String value : reqKey.getValue()) {
                    // Checking the value
                    if (ValidationUtils.isEmpty(value)) {
                        continue;
                    }

                    ...
                }
            }
        }
    }

正如我刚才在对这个问题发表前30分钟发出的另一个问题的答案中写的那样,每次查看所有内容都是浪费。

但是,这些类型的函数在某些情况下仍然有用。 但是,我不是使用“有效”功能,而是将其实现为“崩溃 - 如果坏”功能。 另请注意,此功能仅适用于集合。

一个示例用途是

CrashIfCollection.badNullLength(coll, "coll", Null.BAD, 1);

码:

   import  java.util.Arrays;
   import  java.util.Collection;

enum Null {OK, BAD};

public class CrashIfCollection  {
   public static final void main(String[] ignored)  {
      test(null);
      test(Arrays.asList(new String[] {}));
      test(Arrays.asList(new String[] {"one element"}));
   }
      private static final void test(Collection<?> to_test)  {
         System.out.println("Testing " + ((to_test == null) ? "null"
            :  Arrays.toString(to_test.toArray())));
         try  {
            CrashIfCollection.badNullLength(to_test, "to_test", Null.BAD, 1);
         }  catch(Exception x)  {
            System.out.println(x);
         }
      }
   public static final void badNullLength(Collection<?> coll, String coll_name, Null nullness, int min_len)  {
      try  {
         if(nullness == Null.OK)  {
            if(coll == null)  {
               return;
            }
            if(coll.size() < min_len)  {
               throw  new IllegalArgumentException(coll_name + ".size() (" + coll.size() + ") is less than min_len (" + min_len + ")");
            }
         }
      }  catch(NullPointerException npx)  {
         if(nullness == null)  {
            throw  new NullPointerException("nullness");
         }
         throw  npx;
      }

      //Null.BAD

      try  {
         if(coll.size() < min_len)  {
            throw  new IllegalArgumentException(coll_name + ".size() (" + coll.size() + ") is less than min_len (" + min_len + ")");
         }
      }  catch(NullPointerException npx)  {
         throw  new NullPointerException(coll_name);
      }
   }
}

输出:

Testing null
java.lang.NullPointerException: to_test
Testing []
java.lang.IllegalArgumentException: to_test.size() (0) is less than min_len (1)
Testing [one element]

你可以尝试这样做。 如果您将大小作为私有整数。 您可以执行以下操作:

public boolean isEmpty()
{
    if(size == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

这对我有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM