Using Streams to Convert a List of Objects into a String Obtained from the Tostring Method

Using streams to convert a list of objects into a string obtained from the toString method

One simple way is to append your list items in a StringBuilder

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

StringBuilder b = new StringBuilder();
list.forEach(b::append);

System.out.println(b);

you can also try:

String s = list.stream().map(e -> e.toString()).reduce("", String::concat);

Explanation: map converts Integer stream to String stream, then its reduced as concatenation of all the elements.

Note: This is normal reduction which performs in O(n2)

for better performance use a StringBuilder or mutable reduction similar to F. Böller's answer.

String s = list.stream().map(Object::toString).collect(Collectors.joining(","));

Ref: Stream Reduction

Converting List<String> to String using java streams

If your myList already contains String (or any other CharSequence), then you don't need streams at all, simply call String.join:

String joined = String.join("_", myList);

Otherwise you can use Collectors.joining to produce String from any old stream:

String joined = myList.stream().map(Object::toString).collect(Collectors.joining("_"));

Converting from List of Object to List of String using streams

Because Query.getResultList() returns a raw type List it will break stream pipeline which is heavily based on generic type information. Raw type are effectively removing all information about generic types when used so stream collector returns Object.

You can work around it by manually introducing the generic type with a cast to List<?>:

List<String> collect = ((List<?>) query.getResultList()).stream()
.map(Object::toString)
.collect(Collectors.toList());

Convert a List<String> to Map<String, String> using the list values in Java 8

Here is one way.

  • generate a range of values, i, from 0 to size/2.
  • then use i*2 and i*2 + 1 as the indices into the list.
List<String> data = Arrays.asList("Name", "Sam", "Class",
"Five", "Medium", "English");

Map<String, String> map = IntStream
.range(0,data.size()/2).boxed()
.collect(Collectors.toMap(i -> data.get(i*2),
i -> data.get(i*2+1)));

map.entrySet().forEach(System.out::println);

prints

Medium=English
Class=Five
Name=Sam

Convert a list of Patterns into Predicates using stream

You have mentioned that patterns are String, i.e. it might be List<String>, so you might want to try below:

List<Predicate> predicates = patterns.stream().map(Pattern::compile).map(Pattern::asPredicate)
.collect(Collectors.toList());

Note: you can use List<Predicate<String>> to avoid raw type warning as user @MC Emperor mentioned

Combine lists of 2 different objects into list of single object using Java 8 Stream API

The operation you described is called zipping.

If you are sure the lists are evenly of length, you could do something like:

IntStream.range(0, ids.size())
.mapToObj(i -> new Prediction(ids.get(i), reps.get(i)))
.toList()

Assuming the Prediction class has a constructor like that...

Merge the data relating to each unique Object in a List and transform them into a List of another Type using Streams

Your current solution performs an iteration over the list of customers for every unique id.

As @Johannes Kuhn has pointed out in the comments, you can eliminate redundant iterations by making use of the collector groupingBy(classifier, downstream). With this collector, we can map each customer with unique id to a list of cars in a single iteration.

And then construct a list of ImprovedCustomer objects based on every entry of the map generated by groupingBy().

Note: that in order to use this approach, either Customer class should implement equals/hashCode contract based on the id and name properties, or we need to use an auxiliary record (or class) that would wrap a Customer object. For simplicity, I'll assume that we can rely on the Customer class equals/hashCode implementations.

So, in the code below as classifier function I've applied Function.identity() (i.e. a key would be a customer itself) and as downstream collector a combination of collectors mapping() and toList(), which transforms every customer into a Car object, and collect the cars mapped to the same customer into a list.

public static void main(String[] args) {
List<Customer> customers = // initializing the list of customers

List<ImprovedCustomer> improvedCustomers = customers.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.mapping(cust -> new Car(cust.getCarType(), cust.getColor()),
Collectors.toList())
))
.entrySet().stream()
.map(entry -> new ImprovedCustomer(entry.getKey().getId(), entry.getKey().getName(), entry.getValue()))
.collect(Collectors.toList());
}

Convert a List of Object arrays to a List of model Beans grouped by id

To achieve that, we need to group the data by id and name.

For that, we can create an intermediate map. The key of this map should contain two peaces of information id and name. A quick and dirty way is to concatenate these properties as a string, or wrap them with a list or array of Object type, which even is a more nasty workaround.

The proper way of doing this with Java 8 would to define a separate class as data carrier for the keys and with Java 16 onwards, we can define it as a record. But since you've said that MyBean implements equals/hashCode contract based on the id property, we can use it as key in the intermediate map.

For convenience, I've added one method parse() to the MyBean class (if this change is undesirable, you can extract it away from the class and place this logic into the collector).

public class MyBean {
private Integer id;
private String name;
private Map<String, Object> customAttributes;

public MyBean(Integer id, String name) {
this.id = id;
this.name = name;
}

public static MyBean parse(Object[] args) {
return new MyBean((Integer) args[0], (String) args[1]);
}

// getters, setters, equals/hashCode, toString
}

To generate a map using Stream API we can make use of the collector groupingBy(). As a classifier we need to provide function that creates a key - MyBean based on array Object[]. And a downstream collector we can use a collector that combines all "custom attributes" mapped to the same key into a map.

Then we can create a stream over the entries of the intermediate map and parse each entry into MyBean. And finally collect the beans into a list.

That's how it might look like:

public static void main(String[] args) {
List<Object[]> arrays = buildResultList();

List<MyBean> beans = arrays.stream()
.collect(Collectors.groupingBy(
MyBean::parse,
Collector.of(
HashMap::new,
(Map<String, Object> map, Object[] arr) -> map.put((String) arr[2], arr[3]),
(left, right) -> { left.putAll(right); return left; })
))
.entrySet().stream()
.map(entry -> new MyBean(entry.getKey().getId(),
entry.getKey().getName(),
entry.getValue()))
.collect(Collectors.toList());

beans.forEach(System.out::println);
}

And since MyBean is mutable, take advantage of this by reusing the keys. Note that it's not considered to be a good practice to change the state of the attributes of the lambda expression, for that reason to mutate the key of the map a plain I'm using an enhanced for loop.

public static void main(String[] args) {
List<Object[]> arrays = buildResultList();

Map<MyBean, Map<String, Object>> attributesByBean = arrays.stream()
.collect(Collectors.groupingBy(
MyBean::parse,
Collector.of(
HashMap::new,
(Map<String, Object> map, Object[] arr) -> map.put((String) arr[2], arr[3]),
(left, right) -> { left.putAll(right); return left; })
));

List<MyBean> beans = new ArrayList<>();

for (Map.Entry<MyBean, Map<String, Object>> entry : attributesByBean.entrySet()) {
MyBean k = entry.getKey();
k.setCustomAttributes(entry.getValue());
beans.add(k);
}

beans.forEach(System.out::println);
}

Output:

MyBean{id=3, name='name 3', customAttributes={custom_attr_2=custom_attr_2_val_3}}
MyBean{id=1, name='name 1', customAttributes={custom_attr_2=custom_attr_2_val_1}}
MyBean{id=3, name='name 3', customAttributes={custom_attr_3=custom_attr_3_val_3}}
MyBean{id=3, name='name 3', customAttributes={custom_attr_1=custom_attr_1_val_3}}
MyBean{id=2, name='name 2', customAttributes={custom_attr_3=custom_attr_3_val_2}}
MyBean{id=1, name='name 1', customAttributes={custom_attr_3=custom_attr_3_val_1}}
MyBean{id=2, name='name 2', customAttributes={custom_attr_1=custom_attr_1_val_2}}
MyBean{id=1, name='name 1', customAttributes={custom_attr_1=custom_attr_1_val_1}}
MyBean{id=2, name='name 2', customAttributes={custom_attr_2=custom_attr_2_val_2}}


Related Topics



Leave a reply



Submit