How to create Table where value is number of column key occurrence?

97 Views Asked by At

On the follow data structure Nation as below:

public class Nation {

    String country;

    List<String> States;

For the given sets of nations, intent here is to create a Table with R key country name, C key with state name and value as sum of same state with in the set as show below. Was able to achieve desire results with Map of Map now is it possible to do same with Guava Table ?

    public void someMethod() {
        String name1 = "US";
        String name2 = "Canada";

        List<String> states1 = Arrays.asList("CA", "WA");
        List<String> state2 = Arrays.asList("BC");
        List<String> state3 = Arrays.asList("OR", "CA");

        Nation nation1 = new Nation(name1, states1);
        Nation nation2 = new Nation(name2, state2);
        Nation nation3 = new Nation(name1, state3);
        Nation nation4 = new Nation(name2, state2);

        Set<Nation> nations = new HashSet<>();
        nations.add(nation1);
        nations.add(nation2);
        nations.add(nation3);
        nations.add(nation4);

        final Map<String, Map<String, Integer>> nationToStateCount = new HashMap<>();
        nations.stream().forEach(nation -> {
            nationToStateCount.putIfAbsent(nation.getName(),  new HashMap<>());
            nation.getState().forEach(state ->{
                nationToStateCount.get(nation.getName()).merge(state, 1, Integer::sum);
            });
        });
        
        // Expected Result
        System.out.println(nationToStateCount); // {Canada={BC=2}, US={OR=1, WA=1, CA=2}}

Update: If there is better solution than having if loop and removing and updating values, would be happy to accept that answer.

final Table<String, String, Integer> table = HashBasedTable.create();
nations.stream().forEach(nation -> {
            nation.getState().stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                .forEach((state, count) -> {
                    int value = count.intValue();

                    if(table.contains(nation.getName(), state)) {
                        value += table.get(nation.getName(), state).intValue();
                        table.remove(nation.getName(),state);
                    }

                    table.put(nation.getName(), state, value);
            });
        });
1

There are 1 best solutions below

1
Rajendra Maharjan On

Try something like this:

Note: not sure how you are calculating the counts. static 1 is used below.

Table<String, String, Integer> nTS = HashBasedTable.create();

    nations.stream().forEach(
            x -> {
                x.getStates().forEach(y -> {
                    nTS.put(x.getCountry(), y, 1);
                        }
                );
            });

    System.out.println(nTS);

LINK: Guava maven dependency