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
, from0 to size/2
. - then use
i*2
andi*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
Generate Bank Account Number With Random
How to Convert a Kotlin Source File to a Java Source File
How to Check Type of Variable in Java
Is There a Java Setting for Disabling Certificate Validation
Spring Boot - How to Get Running Port and Ip Address
How to Decrypt Whatsapp Database File
Regular Expression (Regex). How to Ignore or Exclude Everything in Between
Jparepository Findall() Returns Empty Result
Dynamically Change Application.Properties Values in Spring Boot
Multipartexception: Current Request Is Not a Multipart Request
Pass Multiple Parameters to Rest API - Spring
How to Convert Utc Time into Local Time in Java
How to Store User Input into an Existing Array
Null Can Not Be Compared to Double - Why
How to Read File from Relative Path in Java Project? Java.Io.File Cannot Find the Path Specified