If you know for sure that the first two elements of you array have the desire type, you can request the appropriate array type right when creating the copy using Arrays.copyOf
, i.e.
Class1[] arr = ... // [Class2, Class2, Class3, Class3]
Class2[] arr2 = Arrays.copyOf(arr, 2, Class2[].class);
This is not a Java-8 specific solution, but there is no reason to try to use Java-8 features at all costs. The code above will throw a ClassCastException
if your assumption does not hold, but depending on the application logic, this might be better than filtering elements based on their type and silently continuing with different content than expected in the case of an error.
But if you want to filter the elements at runtime, the Stream API does indeed offer the most concise solution:
Class1[] arr = ... // [Class2, Class2, Class3, Class3]
Class2[] arr2 = Arrays.stream(arr)
.filter(Class2.class::isInstance).map(Class2.class::cast)
.toArray(Class2[]::new);
or
Class1[] arr = ... // [Class2, Class2, Class3, Class3]
Class2[] arr2 = Arrays.stream(arr)
.flatMap(o -> o instanceof Class2? Stream.of((Class2)o): null)
.toArray(Class2[]::new);
But note that theses solutions contain more formalism than actually necessary (which is still good for documentation/readability). The toArray
method does not require the result array type to be a supertype of the stream’s element type (simply because Java Generics do not support expressing this requirement), therefore, you don’t need the map
step:
Class2[] arr2 = Arrays.stream(arr).filter(Class2.class::isInstance).toArray(Class2[]::new);
which is the most concise solution with filtering.