简体   繁体   中英

How to map values in a List<Integer> to elements in a List<String> using Stream Api with Java 8

I have the following task.

We have two lists : the first one integerList of type Integer and the second stringList of type String .

The goal is:

  • For each value n from integerList select a string from stringList that starts with a digit and has a length n ;
  • If there are several required strings in the stringList , select the first one;
  • If there's no required string, place "Not found" as an appropriate element.

My code:

public static List<String> foo(List<Integer> integerList, List<String> stringList) {
    return integerList.stream()
        .map(integer -> stringList.stream()
                .filter(...) // not sure what to use here
                .findFirst()
                .orElse("Not found"))
        .collect(Collectors.toList());
}

I'm not sure what should I use in the filter .

Input:

integerList = [1, 3, 4]
stringList = ["1aa", "aaa", "1", "a"]

Desired output:

["1", "1aa", "Not Found"]

You can generate from the list of strings a map Map<Integer,String> , which associates string length with the first string in a list having this length.

And then process the contents of the list of integers.

To filter only those strings that start with a digit , we can use the following regular expression "^//d.*" , which would match any string that has a digit as its first character , followed by zero or more characters.

List<Integer> integerList = List.of(1, 3, 4);
List<String> stringList = List.of("1aa", "aaa", "1", "a");
        
Map<Integer, String> strByLength = stringList.stream()
    .filter(str -> str.matches("^//d.*")) // string starts with a digit
    .collect(Collectors.toMap(
        String::length,        // key
        Function.identity(),   // value
        (left, right) -> left  // pick the first encountered value
    ));
    
List<String> result1 = integerList.stream()
    .map(i -> strByLength.getOrDefault(i, "Not Found"))
    .toList();
    
System.out.println(result1);

Output:

[1, 1aa, Not Found]

It can also be done by creating a nested stream inside map() operation, ie in the way that tried to achieve it. For that, you need to use the following predicate inside the filter() applied before findFirst() :

.filter(str -> str.length() == integer)

Note that such solution is less performant than the first one, which uses Map , because it requires to iterate over the list of string as many times as there are elements in the list of integers. Meanwhile, the map-based approach requires only a single iteration.

Java Strings have a length() method you can use to check the number of characters.

For the first character check you can use the charAt(index) method also available in String.

You can combine this with the Character.isDigit(char) method to check for the requirement.

I guess a solution could look something like this

public static List<String> f(List<Integer> integerList, List<String> stringList) {
    return integerList.stream().map(
        integer -> stringList.stream()
                .filter(s -> s.length() == integer)
                .filter(s -> Character.isDigit(s.charAt(0)))
                .findFirst().orElse("Not found")
    ).collect(Collectors.toList());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM