Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LANG-1634] Add ObjectUtils #applyIfNonNull and #applyFirstNonNull #684

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/main/java/org/apache/commons/lang3/ObjectUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.apache.commons.lang3.exception.CloneFailedException;
Expand Down Expand Up @@ -226,6 +227,63 @@ public static boolean anyNotNull(final Object... values) {
return firstNonNull(values) != null;
}

/**
* <p>
* Calls the given {@code consumer's} {@link Consumer#accept(Object)} method with the first {@code non-null} value
* from {@code objects}. If all the values are null, the consumer is not invoked. This is equivalent to the call
* {@code ObjectUtils.acceptIfNonNull(ObjectUtils.firstNonNull(objects), consumer)}
* </p>
*
* <p>
* The caller is responsible for thread-safety and exception handling of consumer.
* </p>
*
* <pre>
* ObjectUtils.acceptFirstNonNull(bean::setValue, null) - setValue not invoked
* ObjectUtils.acceptFirstNonNull(bean::setValue, null, "abc", "def") - setValue invoked with "abc"
* ObjectUtils.acceptFirstNonNull(v -&gt; bean.setValue(v), "abc") - setValue invoked with "abc"
* </pre>
*
* @param <T> the type of the object
* @param objects the values to test, may be {@code null} or empty
* @param consumer the consumer operation to invoke with the first non-null {@code objects}.
* @see #firstNonNull(Object...)
* @see #acceptIfNonNull(Object, Consumer)
* @since 3.12
*/
@SafeVarargs
public static <T> void acceptFirstNonNull(final Consumer<T> consumer, final T... objects) {
acceptIfNonNull(firstNonNull(objects), consumer);
}

/**
* <p>
* Calls the given {@code consumer's} {@link Consumer#accept(Object)} method with the {@code object} if it is
* {@code non-null}.
* </p>
*
* <p>
* The caller is responsible for thread-safety and exception handling of consumer.
* </p>
*
* <pre>
* ObjectUtils.acceptIfNonNull(null, bean::setValue) - setValue not invoked
* ObjectUtils.acceptIfNonNull("abc", bean::setValue) - setValue invoked with "abc"
* ObjectUtils.acceptIfNonNull("abc", v -&gt; bean.setValue(v)) - setValue invoked with "abc"
* </pre>
*
* @param <T> the type of the object
* @param object the {@code Object} to test, may be {@code null}
* @param consumer the consumer operation to invoke with {@code object} if it is {@code non-null}
* @see #acceptFirstNonNull(Consumer, Object...)
* @since 3.12
*/
public static <T> void acceptIfNonNull(final T object, final Consumer<T> consumer) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more user-friendly: Consumer<? super T> consumer.

Also, requireNonNull(consumer, "consumer").

if (object != null) {
consumer.accept(object);
}
}

// cloning
//-----------------------------------------------------------------------
/**
Expand Down
20 changes: 5 additions & 15 deletions src/main/java/org/apache/commons/lang3/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4391,16 +4391,12 @@ public static String join(final Iterator<?> iterator, final char separator) {

// two or more elements
final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
if (first != null) {
buf.append(first);
}
ObjectUtils.acceptIfNonNull(first, buf::append);

while (iterator.hasNext()) {
buf.append(separator);
final Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
ObjectUtils.acceptIfNonNull(obj, buf::append);
}

return buf.toString();
Expand Down Expand Up @@ -4435,18 +4431,12 @@ public static String join(final Iterator<?> iterator, final String separator) {

// two or more elements
final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
if (first != null) {
buf.append(first);
}
ObjectUtils.acceptIfNonNull(first, buf::append);

while (iterator.hasNext()) {
if (separator != null) {
buf.append(separator);
}
ObjectUtils.acceptIfNonNull(separator, buf::append);
final Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
ObjectUtils.acceptIfNonNull(obj, buf::append);
}
return buf.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.commons.lang3.ArraySorter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Validate;

/**
Expand Down Expand Up @@ -413,9 +414,7 @@ static String[] toNoNullStringArray(final Collection<String> collection) {
static String[] toNoNullStringArray(final Object[] array) {
final List<String> list = new ArrayList<>(array.length);
for (final Object e : array) {
if (e != null) {
list.add(e.toString());
}
ObjectUtils.acceptIfNonNull(e, o -> list.add(e.toString()));
}
return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Validate;

/**
Expand Down Expand Up @@ -224,17 +225,11 @@ private void initializeThread(final Thread thread) {
thread.setName(String.format(getNamingPattern(), count));
}

if (getUncaughtExceptionHandler() != null) {
thread.setUncaughtExceptionHandler(getUncaughtExceptionHandler());
}
ObjectUtils.acceptIfNonNull(getUncaughtExceptionHandler(), thread::setUncaughtExceptionHandler);

if (getPriority() != null) {
thread.setPriority(getPriority().intValue());
}
ObjectUtils.acceptIfNonNull(getPriority(), p -> thread.setPriority(p.intValue()));

if (getDaemonFlag() != null) {
thread.setDaemon(getDaemonFlag().booleanValue());
}
ObjectUtils.acceptIfNonNull(getDaemonFlag(), d -> thread.setDaemon(d.booleanValue()));
}

/**
Expand Down
37 changes: 37 additions & 0 deletions src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;

Expand Down Expand Up @@ -245,6 +246,33 @@ public void testEquals() {
assertTrue(ObjectUtils.equals(FOO, FOO), "ObjectUtils.equals(\"foo\", \"foo\") returned false");
}

@Test
public void testAcceptFirstNonNull() {
final ApplyIfNonNullBean bean = new ApplyIfNonNullBean();
bean.setValue(FOO);

ObjectUtils.acceptFirstNonNull(bean::setValue, null, null, null);
assertEquals(FOO, bean.getValue());

ObjectUtils.acceptFirstNonNull(bean::setValue, null, null, BAR, FOO, null);
assertEquals(BAR, bean.getValue());
}

@Test
public void testAcceptIfNonNull() {
final ApplyIfNonNullBean bean = new ApplyIfNonNullBean();
bean.setValue(FOO);

ObjectUtils.acceptIfNonNull(null, bean::setValue);
assertEquals(FOO, bean.getValue());

ObjectUtils.acceptIfNonNull(BAR, bean::setValue);
assertEquals(BAR, bean.getValue());

ObjectUtils.acceptIfNonNull(FOO, v -> bean.setValue(v));
assertEquals(FOO, bean.getValue());
}

@Test
public void testNotEqual() {
assertFalse(ObjectUtils.notEqual(null, null), "ObjectUtils.notEqual(null, null) returned false");
Expand Down Expand Up @@ -764,4 +792,13 @@ public int compare(final CharSequence o1, final CharSequence o2) {

}

static final class ApplyIfNonNullBean {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = Objects.requireNonNull(value, "value");
}
}
}