3

Say I have a List containing components like the following:

[
    {
        "id": 1,
        "name": "Displacement",
        "value": 200
    },
    {
        "id": 2,
        "name":"Time",
        "value": 120
    },
    {
        "id":3,
        "name":"Mass",
        "value": 233
    },
    {
        "id":4,
        "name": "Acceleration",
        "value": 9.81
    },
    {
        "id": 5,
        "name":"Speed of Light",
        "value": 300000000
    }
]

Each component is an object of the following class:

class Component {
    Integer id;
    String name;
    Long value;

    // necessary getters and setters
}

I need to get the following metrics from the above List: Velocity (Displacement/Time), Force (Mass * Acceleration) and Energy (Mass * Speed of Light^2)

What is the most of doing this? I could stream the list and filter for the necessary components like so:

Double calculateVelocity() {
    Component displacement = list.stream().filter(c -> c.getName().equals("Displacement")).findFirst().orElseThrow(//throw err);
    Component time = list.stream().filter(c -> c.getName().equals("Time")).findFirst().orElseThrow(//throw err);
    return displacement.value / time.value;
} // repeat for other metrics

This would be tedious as the final implementation would have quite a lot more metrics to calculate at a time. Is there any better way?

Thanks

Curiosa Globunznik
  • 3,129
  • 1
  • 16
  • 24
user538578964
  • 723
  • 9
  • 25
  • 5
    What do you find "tedious"? If it's the fact that you need to repeat `list.stream().filter(c -> c.getName().equals("Displacement")).findFirst().orElseThrow(...`)` for each value, how about putting that code in a method, and calling that method? – JB Nizet Oct 26 '19 at 21:19
  • @JBNizet Particularly the method creation, i.e. `calculateVelocity() calculateForce()` etc etc as the actual implementation would have around 20 or so formulae. All these components are retrieved from a DB so ultimately the final goal would be to do all these calculations using SQL queries but until that time, I would prefer the most efficient solution Java-wise. – user538578964 Oct 26 '19 at 21:23
  • 1
    If I were you, I'd precompute a `Map` where the key is the `name` and the value is the `value`. Then, you can calculate velocity as: `(double) map.get("Displacement") / map.get("Time")` – Jacob G. Oct 26 '19 at 21:25
  • @JacobG. I would actually go further and create a dedicated class containing fields for every of those values: double velocity = measures.getDisplacement() / measures.getTime(), since the names of the measures seem to beknown in advance. – JB Nizet Oct 26 '19 at 21:29
  • @JacobG. that's doable.. I was just wondering if there is any Java 8 magic that can be used to pull this off? – user538578964 Oct 26 '19 at 21:29
  • 3
    @user3536523 those formulae won't compute by themselves. You need to have some code implementing them. What you need to do is to model the data so that coding all those methods is easy and safe. Using classes and methods is the answer. 20 formulae, each implemented using simple arithmetic operations, represent 30 or 60 lines of code. It's really not something you should be afraid of. – JB Nizet Oct 26 '19 at 21:30
  • Understood. I had to ask. Our architect gives us a hard time if he sees any code that he thinks can be made generic. I couldn't find an easier way to do it using streams and such so just wanted to make sure I covered all bases. Thanks @JBNizet & JacobG. – user538578964 Oct 26 '19 at 21:38
  • Btw you can convert the list of key/value pairs to a row with one attribute per key on the db level ("unpivot", available e.g. for [oracle](https://www.oracle.com/technical-resources/articles/database/sql-11g-pivot.html) or emulatable by union-all, e.g. in [postgres](https://stackoverflow.com/questions/1128737/unpivot-and-postgresql)). – Curiosa Globunznik Oct 26 '19 at 21:47

0 Answers0