I have the below code to map each entry to a print statement, But it shows error.
Is something wrong in the way I understood Stream().map()?
How do I use System.out.println() within the streams API? how do I correct the following code?
public static void main(String[] args) {
Properties p = new Properties();
p.setProperty("name", "XYX");
p.setProperty("email", "xyx#mail.com");
p.setProperty("address", "addr-street-city");
p.entrySet().stream().map(e ->
System.out.println(" " + e.getKey().toString() + " " + e.getValue().toString() + ""));
}
If you want to use map:
p.entrySet().stream()
.map(e -> " "+e.getKey()+" "+e.getValue())
.forEach(System.out::println);
p.entrySet().forEach(e -> System.out.println(e.getKey() + " " + e.getValue()));
or
p.forEach((key, value) -> System.out.println(key + " " + value));
properties.entrySet().stream()
.map(entry -> String.format("%s : %s", entry.getKey(), entry.getValue()))
.forEach(System.out::println);
.map(...) - convert you key-value to a string format
.forEach(...) - prints your string
Your output should look like that :
address : addr-street-city
email : xyx#mail.com
name : XYX
p.entrySet().forEach(System.out::println)
map() should be used only if you want to alter/modify stream otherwise
for printing to the console forEach would do the work as it accepts BiConsumer to print key and value
Related
I'm matching a list of strings against a list of keywords. The goal is to get a string only one time if it has any of the keywords in it.
Actually I'm doing it with this loop:
for (int i = 0; i < keywords.size(); i++) {
if (text.toLowerCase().contains(keywords.get(i))) {
System.out.println("keyword >>> " + keywords.get(i)
+ " text >>> " + text);
break;
}
}
I like to know if there is a way to get the keyword if I'm using the java stream API like so:
if (keywords.stream().anyMatch(text.toLowerCase()::contains)) {
System.out.println("keyword >>> " + "how to get the keyword here"
+ " text >>> " + text);
}
anyMatch returns a boolean
Using .filter() & findFirst() you can retrieve a value. Note that if you use findFirst() you get an Optional<String> and could either use ifPresent() like this:
keywords.stream()
.filter(keyword -> text.toLowerCase().contains(keyword))
.findFirst()
.ifPresent(keyWord -> System.out.println("[2] keyword >>> " + keyWord + " text >>> " + text));
Or with Optional.isPresent() & Optional.get():
Optional<String> firstKey = keywords.stream()
.filter(keyword -> text.toLowerCase().contains(keyword))
.findFirst();
if (firstKey.isPresent()) {
System.out.println("[2] keyword >>> " + firstKey.get() + " | text >>> " + text);
}
As a less fancy alternative to stream there is a nicer for syntax in Java 1.6+
for(String keyword: keywords) {
if (text.toLowerCase().contains(keyword)) {
System.out.println("keyword >>> " + keyword
+ "text >>> " + text);
break;
}
}
I find the for syntax easier to read than the stream syntax. In a previous job I did a lot of C++ lambda functions with BOOST and the code was hard to parse, and the errors hard to trace.
Another option would be to print an informational message if the keyword was not found. This is easily done by moving the isPresent test inside the print statement.
List<String> keywords =
Arrays.asList("now", "is", "the", "time");
String text = "what are your names?";
Optional<String> opt = keywords.stream()
.filter(keyword -> text
.toLowerCase().contains(keyword))
.findFirst();
System.out.println(!opt.isPresent() ? "No keyword was found!" :
"keyword >>> " + opt.get()
+ " text >>> " + text);
Prints
No keyword was found!
I have a hashmap with 2 objects, Parcel and Deliverer. Both have a getName function. I want to loop the hashmap and print there names like (Parcel.getName(), Deliverer.getName()).
for (Map.Entry<Parcel, Deliverer> entry : deliveryList.entrySet()) {
for (Parcel key: entry) {
System.out.println("Package : " + key.getName());
for (Deliverer deliverer: entry) {
System.out.println("- Deliverer : " + deliverer.getName());
continue;
}
}
}
Another way can be using passing BiConsumer to forEach directly
deliveryList.forEach((key, value) -> System.out.println("Package: " + key.getName() + "- Deliver: " + value.getName()))
Not any different from #funkyjelly. An upvote :)
Same thing, just with Java8 collection foreach syntax.
deliveryList.entrySet().forEach( entry ->
System.out.println("Package : " + entry.getKey().getName());
System.out.println("Deliverer: " + entry.getValue().getName());
);
Once you have the map entries you'd only need to invoke getKey() to get Parcel and getValue() to get Deliverer for each entry.
Hence it should be like this :
for (Map.Entry<Parcel, Deliverer> entry : deliveryList.entrySet()) {
System.out.println("Package : " + entry.getKey().getName() +
"- Deliverer : " + entry.getValue().getName());
}
I have a "for of" on my java code and Im trying to convert to a "for each" with a lambda expression.
for (Bicycle element : bicycleList) {
txtOutput.append("Model:" + element.getModel() + "\n");
}
I have tried to do this:
bicycleList.forEach(txtOutput.append -> ("Model:" + bicycle.getModel() + "\n"));
Can anyone help me?
bicycleList.forEach(element -> txtOutput.append ("Model:" + element.getModel() + "\n"));
You could alternatively use streams as :
String txtOutput = bicycleList.stream()
.map(element -> "Model:" + element.getModel() + "\n")
.collect(Collectors.joining("", "", ""));
I have a multi-level map as follows:
Map<String, Map<String, Student> outerMap =
{"cls1" : {"xyz" : Student(rollNumber=1, name="test1")},
"cls2" : {"abc" : Student(rollNumber=2, name="test2")}}
Now I want to construct a list of string from the above map as follows:
["In class cls1 xyz with roll number 1",
"In class cls2 abc with roll number 2"]
I have written as follows, but this is not working, in this context I have gone through the post as well: Java 8 Streams - Nested Maps to List, but did not get much idea.
List<String> classes = outerMap.keySet();
List<String> studentList = classes.stream()
.map(cls ->
outerMap.get(cls).keySet().stream()
.map(student -> "In class "+ cls +
student + " with roll number " +
outerMap.get(cls).get(student).getRollNum() +"\n"
).collect(Collectors.toList());
You can simply use Map.forEach for this operation as:
List<String> messages = new ArrayList<>();
outerMap.forEach((cls, students) ->
students.forEach((name, student) ->
messages.add(convertToMessage(cls, name, student.getRollNumber()))));
where convertToMessage is a util as :
// this could be made cleaner using 'format'
String convertToMessage(String cls, String studentName, String rollNumber) {
return "In class" + cls + "--> " + studentName + " with roll number: " + rollNumber;
}
You may do it like so,
List<String> formattedOutput = outerMap
.entrySet().stream()
.flatMap(e -> e.getValue().entrySet().stream().map(se -> "In class " + e.getKey()
+ " " + se.getKey() + " with roll number " + se.getValue().getRollNumber()))
.collect(Collectors.toList());
You have to use the flatMap operator instead of map operator.
One method use Java 8 Stream and lambda function:
String format = "In class %s %s with roll number %d";
List<String> result = new ArrayList<>();
outerMap.entrySet().stream()
.forEach(v -> {
String className = v.getKey();
v.getValue().entrySet().stream()
.forEach(stringStudentEntry -> result.add(String.format(format,className,stringStudentEntry.getKey(),stringStudentEntry.getValue().getRollNumber())));
});
Hi rectors all aver the world. I'm doing reactivi programming in Java. I'm a java/grails/react developer but first steps with reactive programming with Spring Boot, version 2 M7 in this case. In the next code:
#GetMapping(API_BASE_PATH + "/flux4")
public String flux4() {
StringBuilder sb = new StringBuilder();
Flux.just("alpha", "bravo", "charlie")
.map(String::toUpperCase)
.flatMap(s -> Flux.fromArray(s.split("")))
.groupBy(String::toString)
.sort(Comparator.comparing(GroupedFlux::key))
.map(group -> group.key() + " => " + group.count() + "; ")
.subscribe(sb::append);
return "flux 4: " + sb.toString();
}
I get the group.key() printed but how caon I get printed the group.count() ?
Any help is welcome
Cheers
Juan
I think I am reading the same book as you :)
Here is the solution using block().
Flux.just("alpha", "beta", "charlie")
.map(String::toUpperCase)
.flatMap(s -> Flux.fromArray(s.split("")))
.groupBy(String::toString)
.sort((o1,o2) -> o1.key().compareTo(o2.key()))
.flatMap(group -> Mono.just(Tuples.of(group.key(), group.count().block())))
.map(keyAndCount -> keyAndCount.getT1() + " => " + keyAndCount.getT2() + "; ")
I am wondering if there is an alternate way that doesn't call block()?. Now group.count() returns a Mono<Long>, and group.key() returns a String. It would be good if we could combine the two to form a Mono<Tuple2<String, Long>> without having to evaluate the result of the Mono. Seems like there should be a general method for doing that?
The book tried to use:
Mono.just(group.key()).and(group.count())
But that just listens for the completion events and returns a Mono<Void>, and therefore gives me compile errors...
Addendum: found it! Use the zip method:
Flux.just("alpha", "beta", "charlie")
.map(String::toUpperCase)
.flatMap(s -> Flux.fromArray(s.split("")))
.groupBy(String::toString)
.sort((o1,o2) -> o1.key().compareTo(o2.key()))
.flatMap(group -> Mono.zip(Mono.just(group.key()), group.count()))
.map(keyAndCount -> keyAndCount.getT1() + " => " + keyAndCount.getT2() + "; ")