Skip to content
Closed
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
60 changes: 60 additions & 0 deletions src/main/java/org/apache/commons/lang3/ArrayUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
Expand Down Expand Up @@ -8862,6 +8865,63 @@ public static <T> T[] toArray(@SuppressWarnings("unchecked") final T... items) {
return items;
}

/**
* Converts an {@link Iterator} into an array.
* <p>
* Returns {@code null} if the input iterator is {@code null}.
* If the iterator has no elements, an empty {@code Object[]} is returned.
* </p>
* <p>
* Note: The returned array has runtime type {@code Object[]}, and requires that all elements
* in the iterator are of the same type. If a type-safe array is needed, use
* {@link #iteratorToArray(Iterator, Class)} instead.
* </p>
*
* @param iterator the iterator to convert, may be {@code null}
* @param <T> the element type
* @return the array containing elements from the iterator,
* or {@code null} if the input is {@code null}
* @since 3.18
*/
@SuppressWarnings("unchecked")
public static <T> T[] iteratorToArray(Iterator<T> iterator) {
Comment thread
ppkarwasz marked this conversation as resolved.
if (iterator == null) {
return null;
}

if (!iterator.hasNext()) {
return (T[]) ArrayUtils.EMPTY_OBJECT_ARRAY;
}

return (T[]) Streams.of(iterator).toArray();
}

/**
* Converts an {@link Iterator} into a typed array.
* <p>
* Returns {@code null} if the input iterator or class is {@code null}.
* If the iterator has no elements, an empty array of the specified type is returned.
* </p>
*
* @param iterator the iterator to convert, may be {@code null}
* @param clazz the class of the array component type, must not be {@code null}
* @param <T> the element type
* @return the array containing elements from the iterator, or {@code null} if the input is {@code null}
* @since 3.18
*/
@SuppressWarnings("unchecked")
public static <T> T[] iteratorToArray(Iterator<T> iterator, Class<T> clazz) {
if (iterator == null || clazz == null) {
return null;
}

final List<T> list = new ArrayList<>();
iterator.forEachRemaining(list::add);

final T[] array = (T[]) Array.newInstance(clazz, list.size());
return list.toArray(array);
}
Comment thread
ppkarwasz marked this conversation as resolved.

/**
* Converts the given array into a {@link java.util.Map}. Each element of the array
* must be either a {@link java.util.Map.Entry} or an Array, containing at least two
Expand Down
50 changes: 50 additions & 0 deletions src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.function.Function;
Expand Down Expand Up @@ -6452,6 +6453,55 @@ void testTextIndexesOfInt() {
assertEquals(emptySet, ArrayUtils.indexesOf(array, 99));
}

@Test
void testIteratorToArray() {
final Iterator<String> iterator = Arrays.asList("one", "two", "three").iterator();
final Object[] normalResult = ArrayUtils.iteratorToArray(iterator);

assertArrayEquals(new Object[]{"one", "two", "three"}, normalResult);

final Iterator<Object> emptyIterator = Collections.emptyIterator();
final Object[] emptyArray = ArrayUtils.iteratorToArray(emptyIterator);

assertEquals(0, emptyArray.length);
assertNull(ArrayUtils.iteratorToArray(null));

final Iterator<Integer> singletonIterator = Collections.singletonList(42).iterator();
final Object[] result = ArrayUtils.iteratorToArray(singletonIterator);

assertEquals(1, result.length);
assertEquals(42, result[0]);

final Iterator<?> mixed = Arrays.asList(1, "two", 3.0).iterator();
final Object[] mixedResult = ArrayUtils.iteratorToArray(mixed);

assertArrayEquals(new Object[]{1, "two", 3.0}, mixedResult);
}

@Test
void testIteratorToArrayWithClazz() {
final Iterator<String> it1 = Arrays.asList("a", "b", "c").iterator();
final String[] result1 = ArrayUtils.iteratorToArray(it1, String.class);
assertArrayEquals(new String[] {"a", "b", "c"}, result1);

final Iterator<Integer> it2 = Collections.<Integer>emptyList().iterator();
final Integer[] result2 = ArrayUtils.iteratorToArray(it2, Integer.class);
assertNotNull(result2);
assertEquals(0, result2.length);

final String[] result3 = ArrayUtils.iteratorToArray(null, String.class);
assertNull(result3);

final Iterator<Double> it4 = Arrays.asList(1.1, 2.2).iterator();
final Double[] result4 = ArrayUtils.iteratorToArray(it4, null);
assertNull(result4);

final Iterator<String> it5 = Arrays.asList("x", null, "z").iterator();
final String[] result5 = ArrayUtils.iteratorToArray(it5, String.class);
assertArrayEquals(new String[] {"x", null, "z"}, result5);
}


@Test
void testToMap() {
Map<?, ?> map = ArrayUtils.toMap(new String[][] { { "foo", "bar" }, { "hello", "world" } });
Expand Down