Reputation: 19
We started with streams and lambdas today in programming class and i have to do an exercise.
The first task was to write a method that calculates the average of even numbers in a list. I have written this code but obviously i did not make use of streams.
public static double average(List<Integer> list) {
double sum = 0;
int i = 0;
for (Integer integer : list) {
if (integer % 2 == 0) {
i++;
sum += integer;
}
}
return (sum / i);
}
EDIT Solution:
int sum = list.stream().filter(integer -> integer % 2 == 0).mapToInt(Integer::intValue).sum();
long count = list.stream().filter(integer -> integer % 2 == 0).count();
The second task was to write a method that selects all strings that start with "a" (case insensitive) or have 3 characters and change it to upper case. My code:
public static List<String> upperCase(List<String> list) {
for(int i = 0; i < list.size(); i++){
if(list.get(i).length() == 3 || Character.toString(list.get(i).charAt(0)).equalsIgnoreCase("a")){
list.set(i, list.get(i).toUpperCase());
}
}
return list;
}
EDIT: Solution:
public static List<String> upperCase(List<String> list) {
List<String> newListOfStrings = list.stream().map(string -> string.length() == 3 ||
Character.toString(string.charAt(0)).equalsIgnoreCase("a") ? string.toUpperCase() : string).collect(Collectors.toList());
return newListOfStrings;
The last task was to return the list but add "g" to even numbers and "u" to odd numbers. My code:
public static String getString(List<Integer> list){
String s = "";
for(Integer integer : list){
if(integer % 2 == 0){
s += integer.toString() + "g,";}
else {
s += integer.toString()+ "u,";
}
}
return s.substring(0, s.length()-1);
}
EDIT: Solution:
public static String getString (List < Integer > list) {
String result = list.stream()
.map(integer -> integer % 2 == 0 ?
String.format("%d%s", integer, "g") : String.format("%d%s", integer, "u"))
.collect(Collectors.joining(","));
return result;
I would really appreciate if someone could tell me how the first task would look like with streams. I will try the two others on my own.
Kind regards
Upvotes: 0
Views: 80
Reputation: 44496
The first task was to write a method that calculates the average of even numbers in a list.
The point is to change the boxed Stream<Integer
to IntStream
which provides method for aggregating operation such as sum, average, min, max etc.
double average = list.stream().mapToInt(i -> i).average().getAsDouble;
Remember, the NoSuchElementException
might be thrown if no average is present in OptionalDouble
.
The second task was to write a method that selects all strings that start with "a" (case insensitive) or have 3 characters and change it to upper case.
You forEach
method at the end of the stream is a terminal operation that requires a Consumer
, which consumes the method. Although you call toUpperCase
, it doesn't change the original collection and the result is thrown (unless you print it out).
You wan to perform the mapping of the qualified strings using method map
. As long as you want only to modify these values and keep the remaining at the same time, you cannot use filter
as long as it can modify the number of items streamed. Do this:
List<String> newListOfStrings = listOfStrings.stream()
.map(string -> string.length() == 3 || string.startsWith("a") ?
string.toUpperCase() : string)
.collect(Collectors.toList());
Notice I have used startsWith
method that is easier to use. Your usage of charAt
is not incorrect, though.
The last task was to return the list but add "g" to even numbers and "u" to odd numbers.
Not the best, but fairly acceptable solution is again using mapping method map
and finally Collectors.joining(",")
that joins the items to a string with a delimiter. Therefore you don't need to bother with ,
characters.
String result = list.stream()
.map(integer -> integer % 2 == 0 ? integer + "g" : integer + "u")
.collect(Collectors.joining(","));
// I find String.format better than using +
String result = list.stream()
.map(integer -> integer % 2 == 0 ?
String.format("%d%s", integer, "g") : String.format("%d%s", integer, "u"))
.collect(Collectors.joining(","));
However, if I were to implement the 3rd one, I would use simple for-each iteration and StringBuilder
that is suitable for the string concatenation:
StringBuilder sb = new StringBuilder();
for (Integer integer: list) {
sb.append(integer);
if (integer % 2 == 0) {
sb.append("g,");
} else {
sb.append("u,");
}
}
String result = sb.toString().substring(0, sb.length() - 1);
... or using a new collection with String.join
method ...
List<String> newList = new ArrayList<>();
for (Integer integer: list) {
String toAdd = integer % 2 == 0 ?
String.format("%d%s", integer, "g") :
String.format("%d%s", integer, "u");
newList.add(toAdd);
}
String result = String.join(",", newList);
Upvotes: 2