0

I have multiple Gateways which gives the information of various devices along with the distance. I want to extract information like which device is having a low distance in which gateway. Currently, I combined the results into HashMap within HashMap like this code:

Map<String, Map<String, Double>> averageDistances = calculateAverageDistances(data);

for (Map.Entry<String, Map<String, Double>> entry : averageDistances.entrySet()) {
            String gateway = entry.getKey();
            System.out.println("Gateway: " + gateway);

            Map<String, Double> deviceDistances = entry.getValue();
            for (Map.Entry<String, Double> deviceEntry : deviceDistances.entrySet()) {
                String device = deviceEntry.getKey();
                double averageDistance = deviceEntry.getValue();
                System.out.println("Device: " + device + ", Average Distance: " + averageDistance);
             }
        }

Which is showing the result like that:

Gateway: AC233FC0FA9F
Device: AC233FAC9623, Average Distance: 7.1
Device: AC233FAC9624, Average Distance: 4.3
Gateway: AC233FC0FAAE
Device: AC233FAC9623, Average Distance: 11.850000000000001
Device: AC233FAC9624, Average Distance: 0.8

I want the final result like as a device(AC233FAC9623) is present in both gateways(AC233FC0FA9F and AC233FC0FAAE), it is having a lower distance in the gateway(AC233FC0FA9F) so consider this record only. Same as the device(AC233FAC9624) is having a lower distance in the gateway(AC233FC0FAAE) so consider this record. A final output should be like this:

Gateway: AC233FC0FA9F
Device: AC233FAC9623, Average Distance: 7.1

Gateway: AC233FC0FAAE
Device: AC233FAC9624, Average Distance: 0.8

Can someone hint which data structure should be used here?

Jemshit
  • 9,501
  • 5
  • 69
  • 106
user565
  • 871
  • 1
  • 22
  • 47
  • Does this answer your question? [How to Flatten a HashMap?](https://stackoverflow.com/questions/54183766/how-to-flatten-a-hashmap) – aled Jul 17 '23 at 02:27
  • Consider using the device as the key, and the gateway and distance as the value. – Reilas Jul 17 '23 at 04:01
  • What is `data`? What is the code of `calculateAverageDistances`? – trincot Jul 17 '23 at 08:24

2 Answers2

0

Maintain a Map from device to a preferable gateway . Here is an example:

    // key - device, value - pair of preferable gateway and distance
    Map<String, Map.Entry<String, Double>> deviceToLowestDistance = new HashMap<>();

    for (Map.Entry<String, Map<String, Double>> entry : averageDistances.entrySet()) {
        Map<String, Double> deviceDistances = entry.getValue();
        for (Map.Entry<String, Double> deviceEntry : deviceDistances.entrySet()) {
            deviceToLowestDistance.compute(
                    deviceEntry.getKey(),
                    (k, currentLowestEntry) -> {
                        if (currentLowestEntry == null || deviceEntry.getValue() < currentLowestEntry.getValue()) {
                            return deviceEntry;
                        } else {
                            return currentLowestEntry;
                        }
                    }
            );
        }
    }

    // if you don't need to group devices with lowest distances by gateway, then deviceToLowestDistance in enough. Otherwise group them:

    // key - gateway, value - devices with lowest distances only
    Map<String, Map<String, Double>> gatewaysWithLowestDistances = new HashMap<>();
    deviceToLowestDistance.forEach((device, gatewayToDistance) -> {
                String gateway = gatewayToDistance.getKey();
                Double lowestDistance = gatewayToDistance.getValue();
                gatewaysWithLowestDistances.computeIfAbsent(gateway, k -> new HashMap<>()).put(device, lowestDistance)
            }
    );
    
    // print gatewaysWithLowestDistances in any way
gdomo
  • 1,650
  • 1
  • 9
  • 18
0

It seems like you wish, for each gateway, to have a list of devices closest to that gateway, and also include information about the distance.

So first, build a temporary structure where each device keeps track of the gateway closest to it. Then, reverse the order of the structure, using the gateway ID as key.

    Map<String, Map<String, Double>> averageDistances = calculateAverageDistances(data);

    findClosestGateway(averageDistances).forEach((gatewayID, devices) -> {
        System.out.println("Gateway: " + gatewayID);
        devices.forEach(device -> System.out.println("Device: " + device.id + ", Average Distance: " + device.distance));
    });


private record Device(String id, double distance) {};

private Map<String, List<Device>> findClosestGateway(Map<String, Map<String, Double>> averageDistances) {
    record Gateway(String id, double distance) {};
    var devices = new HashMap<String, Gateway>();
    averageDistances.forEach((gatewayID, distances) -> distances.forEach((deviceID, distance) -> {
        var currentClosestGateway = devices.get(deviceID);
        if (currentClosestGateway == null || currentClosestGateway.distance > distance) {
            devices.put(deviceID, new Gateway(gatewayID, distance));
        }
    }));
    var result = new HashMap<String, List<Device>>();
    devices.forEach((deviceID, gateway) -> {
        result.computeIfAbsent(gateway.id, k -> new ArrayList<>()).add(new Device(deviceID, gateway.distance));
    });
    return result;
}

Note that if there are devices which are equidistant to two or more gateways, which gateway is chosen is arbitrary because we are using HashMap here. If you wish to have more control in this edge case, use LinkedHashMap or TreeMap instead, depending on your needs.

NorthernSky
  • 488
  • 2
  • 10