Java 8 - Filter a string-X from a list using startsWith and Save the String-X to a list

Viewed 17979

I am new to Java 8 and trying to get my head around how streams and filter works with list. I have a list of predefined strings and I have a string value which I am processing. I want to add the processed string to a new list if the string starts with any of the strings in the predefined list. If the string doesn't match any strings from the list then save it to another list.

For example:

List<String> internalIpAddresses= new ArrayList<>();
List<String> externalIpAddresses = new ArrayList<>();

List<String> ipAddresseses = new ArrayList<String>();
ipAddresses.add("10.");
ipAddresses.add("132.174.");
ipAddresses.add("192.168.");

// filter internal ip addresses
for(String ipAddress : ipAddresseses){

     if("10.11.12.13".startsWith(ipAddress)) {
          internalIpAddresses.add("10.11.12.13");
     }
}

// filter external ip addresses
for(String ipAddress : ipAddresseses){

     if(!"5.6.7.8".startsWith(ipAddress)) {
          externalIpAddresses .add("5.6.7.8");
     }
}

Result:

internalIpAddresses: 10.11.12.13
externalIpAddresses : 5.6.7.8 

Is there a way this can be achieved in a simpler way using stream in java 8?

Like:

ipAddresseses.stream()
     .filter(ipAddress -> clientIpAddress.startsWith(ipAddress)
     .*if the clientIpAddress starts with any of the values in the list then add to internalIpAddresses List
     .*if clientIpAddress doesn't start with any values in list then add to externalIpAddresses List

In the end I want to save the clientIpAddress ("10.11.12.13" or "5.6.7.8"), not the values from the ipAddresses ("10." or "192.168.") list.

4 Answers

Simply, your iterative code using streams could be represented as :

List<String> ipAddresses = Arrays.asList("10.", "132.174.", "192.168.");

List<String> internalIpAddresses = ipAddresses.stream()
        .filter("10.11.12.13"::startsWith)
        .map(ipAddress -> "10.11.12.13")
        .collect(Collectors.toList());

List<String> externalIpAddresses = ipAddresses.stream()
        .filter(ipAddress -> !"5.6.7.8".startsWith(ipAddress)) // I doubt this should be '.filter("5.6.7.8"::startsWith)'
        .map(ipAddress -> "5.6.7.8")
        .collect(Collectors.toList());

A general approach as suggested in comments for solving this could be using:

List<String> internalIpAddresses = Stream.of("10.11.12.13") // can add more addresses
        .filter(ip -> ipAddresses.stream().anyMatch(ip::startsWith))
        .collect(Collectors.toList());

You can try :

ipAddresseses.stream()
 .collect(Collectors.partitioningBy(ipAddress -> ipAddress.startsWith("10.11.12.13")));

This will give a Map with two elements, one with good ipAddress and one with bad.

You can do this -

  ipAddresseses.stream().foreach( ipaddress 
 -> decideGoodOrBadAndAdd(s);

Create one method which will check if it's good or bad ip address and add it in respective list accordingly-

  public void decideGoodOrBadAndAdd(String 
  ipaddress){

  if("10.11.12.13".startsWith(ipAddress)) {
        goodIpAddresses.add(ipAddress);
   }
  else if(!"5.6.7.8".startsWith(ipAddress)) {
        badIpAddresses.add(ipAddress);
   }
}

You can do so using :

Map<Boolean, List<String>> ipMap = ipAddresses.stream()
               .collect(Collectors.partitioningBy(ipAddress -> ipAddress.startsWith("10.")));

goodIpAddresses.addAll(ipMap.get(true));
badIpAddresses.addAll(ipMap.get(false));

Here the map ipMap will contain only two keys depending on the predicate in partitioningBy()

To fetch the ip's needed to be added to the goodIpAddresses just use the key true and to fetch the ip's for badIpAddresses use the key false.

Related