6

Is there a simple way in Java (that doesn't involve writing a for-loop) to create an array of objects from a property of another array of different objects?

For example, if I have an array of objects of type A, defined as:

public class A {
    private String p;
    public getP() {
        return p;
    }
}

I want to create an array of Strings that contains the value of A[i].p for each i.

Essentially, I'm I want to do this: Creating an array from properties of objects in another array, but in Java.

I attempted to use Arrays.copyOf(U[] original, int newLength, Class<? extends T[]> newType) along with a lambda expression, but that didn't seem to work. What I tried:

Arrays.copyOf(arrayA, arrayA.length, (A a) -> a.getP());
Community
  • 1
  • 1
rom58
  • 103
  • 2
  • 6

2 Answers2

11

With Java 8, you can use the Stream API and particularly the map function:

A[] as = { new A("foo"), new A("bar"), new A("blub") };
String[] ps = Stream.of(as).map(A::getP).toArray(String[]::new);

Here, A::getP and String[]::new are method/constructor references. If you do not have a suitable method for the property you want to have, you could also use a lambda function:

String[] ps = Stream.of(as).map(a -> a.getP()).toArray(String[]::new);
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • 1
    How is `a -> a.getP()` different from `A::getP`? – rom58 May 12 '16 at 16:43
  • 1
    It's not. It's a method reference for a lambda expression. – Kedar Mhaswade May 12 '16 at 16:47
  • @rom58 In this case, they are equivalent, but the method reference should be preferred, as it more clearly conveys that it will use just that method and nothing else. Use the lambda if you need a function without an existing method, for example `a -> a.getP().trim().toUpperCase()` (although this could also be done with method references and three `map` in a row. – tobias_k May 12 '16 at 18:13
2

This is where a powerful concept in functional programming called map is useful. Here's how map is defined:

map :: (a -> b) -> [a] -> [b]

Thus, map is a function that takes a function (that takes a and returns b) and a list and returns a list. It applies the given function to each element of the given list. Thus map is a higher order function.

In Java 8, you can use this idiom if you can convert the array into a stream. This can be done simply:

Arrays.stream(array).map(mappingFunction);

where the mappingFunction takes an element from stream (say of type A) and converts it to another (say of type B). What you now have is a stream of B's, which you can easily collect in a collector (e.g. in a list, or an array) for further processing.

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
  • This gives a stream. To convert to an array, you need to use `Stream.toArray()` like used in the other comment. – Naeio Dec 31 '19 at 00:46