Assuming I have a Stream<String>
, what is the most succinct way with which I could obtain a Stream<CustomType>
where each element of Stream<CustomType>
has each element of Stream<String>
as value for the one of its member variables:
E.g.:
class CustomType {
private String id;
public void setId(String id) {
this.id = id;
}
}
class Test {
public static void main (String... args) {
Stream<String> source = Stream.of("A", "B", "C");
Stream<CustomType> result = source.map(s -> {
CustomType obj = new CustomType();
obj.setId(s);
return obj;
});
}
}
Is there a way to shorten this?
Later edits: Looking for a way other than overriding constructor of CustomType
, and to avoid coding the boilerplate of manually creating CustomType
objects CustomType obj = new CustomType();
i.e. somehow have Stream API create CustomType
objects for me so I could just specify what setter (e.g.: setID()
) the String
s should be set to.
CodePudding user response:
If you can change the constructor for your custom type, you can do:
class CustomType {
private String id;
public CustomType(String id) {
this.id = id;
}
public void setId(String id) {
this.id = id;
}
}
class Test {
public static void main (String... args) {
Stream<String> source = Stream.of("A", "B", "C");
Stream<CustomType> result = source.map(CustomType::new);
}
}
If you can't add a new constructor, the best you can do is move the setting logic outside of the stream processor, like so:
class Test {
public static void main (String... args) {
Stream<String> source = Stream.of("A", "B", "C");
Stream<CustomType> result = source.map(Test::customTypeWithId);
}
private static CustomType customTypeWithId(String id) {
CustomType obj = new CustomType();
obj.setId(s);
return obj;
}
}
CodePudding user response:
For any CustomType
you could do it like this.
- define a Function to create an instance and set the value;
- then call the method with the source Stream and that function to return the new Stream
Stream<String> source = Stream.of("A", "B", "C");
Function<String,CustomType> fnc = (str) -> {
CustomType t = new CustomType();
t.setId(str);
return t;};
Stream<CustomType> stream = customStream(source, fnc);
public static <T> Stream<T> customStream(Stream<String> source,
Function<String, T> fnc) {
Builder<T> builder = Stream.builder();
source.forEach(k -> builder.add(fnc.apply(k)));
return builder.build();
}
Of course it would be better if your custom types implemented an interface that had T setId(String s)
as the method. Here is an example of that:
interface SetIDInterface<T> {
public T setId(String s);
}
class CustomType implements SetIDInterface<CustomType> {
public String id;
public CustomType setId(String id) {
this.id = id;
return this;
}
}
Stream<String> source = Stream.of("A", "B", "C");
Stream<CustomType> stream = customStream(source, CustomType::new);
public static <T extends SetIDInterface<T>> Stream<T>
customStream(Stream<String> source, Supplier<T> sup) {
Builder<T> builder = Stream.builder();
source.forEach(k -> builder.add(sup.get().setId(k)));
return builder.build();
}