3

I have written the below code in Java and trying to convert the same to Java 8. The code works as expected for the input (a List created by createTempList method) and output(a map whose key is the 1st decimal of the string and value is the other decimals of the string)

public static void main(String[] args) {
    List<String> tempList = createTempList();
    createMap8(tempList);
}

public static Map<String,List<String>> createMap8(final List<String> tempList) {
    Map<String,List<String>> vlanFoos = new HashMap<String,List<String>>();
    for(int i=0; i< tempList.size(); i++) {
        String[] idsI = tempList.get(i).split("\\.");
        String vlanI = idsI[0];
        List<String> fooList = new ArrayList<String>();
        for(int j = 0 ; j < tempList.size() ; j ++) {
            String foo = "";
            String[] idsJ = tempList.get(j).split("\\.");
            String vlanJ = idsJ[0];
            if(vlanI.equals(vlanJ)) {
                        for(int k = 1; k < idsJ.length; k++) {
                            foo = foo + idsJ[k];
                            if(idsJ.length - k != 1) {
                                foo = foo + ".";
                            }
                        }
            }
            if(!foo.isEmpty()) {
                fooList.add(foo);
            }
        }
        vlanFoos.put(vlanI, fooList);
    }
    return vlanFoos;
}

Input :

private static List<String> createTempList() {
    List<String> tempList = new ArrayList<String>();
    tempList.add("1.24.75.13.45.91.0");
    tempList.add("1.88.213.110.66.182.127");
    tempList.add("1579.204.45.224.38.12.161");
    tempList.add("1580.204.45.224.38.12.161");
    tempList.add("21.204.45.224.38.12.161");
    tempList.add("39.204.45.224.38.12.161");
    tempList.add("5.12.244.213.2.178.192");
    tempList.add("5.204.45.224.38.12.161");
    tempList.add("5.212.202.109.116.154.217");
    tempList.add("5.212.202.109.116.154.218");
    tempList.add("5.40.153.58.148.24.67");
    tempList.add("5.76.177.205.33.164.80");
    tempList.add("5.84.236.47.13.223.64");
    tempList.add("5.88.213.110.66.182.128");
    return tempList;
}

Output :

 {1=[24.75.13.45.91.0, 88.213.110.66.182.127], 
 1579=[204.45.224.38.12.161], 
 5=[12.244.213.2.178.192, 204.45.224.38.12.161, 212.202.109.116.154.217, 212.202.109.116.154.218, 40.153.58.148.24.67, 76.177.205.33.164.80, 84.236.47.13.223.64, 88.213.110.66.182.128], 
 39=[204.45.224.38.12.161], 
 1580=[204.45.224.38.12.161], 
 21=[204.45.224.38.12.161]}
Tiya
  • 553
  • 8
  • 26

3 Answers3

2

This is probably the most concise way to do it:

public static Map<String, List<String>> createMap8(final List <String> tempList) {
    return tempList.stream()
                   .map(s -> s.split("\\.", 2))
                   .collect(groupingBy(p -> p[0], mapping(a -> a[1], toList())));
}

For the createTempList method, you can just use Arrays.asList

ETO
  • 6,970
  • 1
  • 20
  • 37
user
  • 7,435
  • 3
  • 14
  • 44
2

After modifying your data you can do this:

Map<String, List<String>> map = tempList.stream()
         .map(t -> t.split("\\.", 2))
         .collect(Collectors.toMap(a -> a[0], v -> new ArrayList<>(singletonList(v[1])),
                                   (l1, l2) -> {l1.addAll(l2); return l1;}
                                  )
                 );
Hadi J
  • 16,989
  • 4
  • 36
  • 62
1

I suggest you create another class to do the string parsing stuff:

// please give this a better name!
// I don't know what the numbers mean, but you should!
class MyObject {
    private String key;
    private String value;

    public String getKey() {
        return key;
    }

    public String getValue() {
        return value;
    }

    public MyObject(String s) {
        // here I split the string into the first and the rest
        String[] parts = s.split("\\.", 2);
        key = parts[0];
        value = parts[1];
    }
}

Then with streams, the grouping by can be done like this:

public static Map<String,List<String>> createMap8(final List<String> tempList) {

    return tempList.stream().map(MyObject::new).collect(
            Collectors.groupingBy(
                    MyObject::getKey, Collectors.mapping(MyObject::getValue, Collectors.toList())
            )
    );
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Thank you for your response. Having another object is definitely cleaner and better. However, my return Object (Map that I used or MyObject that you used ) will be sent to the Jaxrs caller. The calling method does not have any idea about this Object, hence, trying to use Map. – Tiya Apr 25 '20 at 14:10
  • @Tiya I'm not telling you to return a `Map>` instead. You can still return a `Map>`. Did you try my solution? – Sweeper Apr 25 '20 at 14:11
  • 1
    @Tiya See the edit. As you can see, your method's signature does not need to change at all. Hope that makes it clearer now. – Sweeper Apr 25 '20 at 14:14
  • creating an object is not necessary. `split("\\.",2)` – Hadi J Apr 25 '20 at 14:25
  • 1
    @HadiJ I just love giving names to things... A `String[]` tells you so little about the structure of the data it stores, other than "it's a bunch of strings". The class might come in handy later on, who knows? Thanks for reminding of the second argument to `split` though. – Sweeper Apr 25 '20 at 14:29