0

Within a particular class (Assets), I have a series of related variables like so:

private long checkingBalance;
private long savingsBalance;
private long moneyMarketBalance;

...the list goes on.

Logically, I know they're all related, so I want to add up all of these variables and display the sum. What I don't want to do is manually type out

total = checkingBalance + savingsBalance + moneyMarketBalance + indexFundBalance + mutualFundBalance + whatever 

and so forth. I feel like there must be a better way of doing this.

So, is there? I'm thinking there's got to be a way to define some sort of arbitrary set or collection and just tell Java to loop through it and add up all its members. Should I create another class called Balances or something with all those variables as attributes? Otherwise I considered using an array but that seems hackish.

Thanks!

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
Ivan
  • 1,427
  • 1
  • 16
  • 26

5 Answers5

2

I'm going to guess that you're coming from a LISPy background. What you're looking for does not exist in java.

You can certainly create a class to wrap it. You could create a list of assets, and have a function that iterates over a list. There's no native map-to behaviour in java collections though.

Map<String,Integer> assets = new HashMap();

int total(){
   int total=0;
   for(Integer x: assets.values()){
       total+= x;
   }
   return total;
}
InfernalRapture
  • 572
  • 7
  • 19
  • The Hashmap assumes you want to be able to retrieve by name or something. If the asset itself has no inherent value that requires it to be distinct you'd make a running total. EnumMap would work very well too I think, if your assets are constrained. – InfernalRapture Nov 14 '13 at 03:44
1

This is what data structures are for.

You could either make a list, or a map for all these values if you want to iterate over them frequently. In your example, a map called Balances seems appropriate.

private Map<String, Long> balances = new HashMap<String, Long>();
balances.put('someBalance', new Long(0));

Of course, this is purely a design decision.

slider
  • 12,810
  • 1
  • 26
  • 42
1

Using reflection API is one way (http://docs.oracle.com/javase/tutorial/reflect/member/fieldTypes.html)

J.Koskela
  • 421
  • 1
  • 6
  • 19
1

you could use Java reflection to find the fields of a class:

How to get the fields in an Object via reflection?

If it's one or a few classes you created, i'd type it out and be done. If it's an arbitrary class where you don't know which fields or how many, reflection is the way to go.

Community
  • 1
  • 1
prototype
  • 7,249
  • 15
  • 60
  • 94
1
public class Test {
    private long xBalance = 5L;
    private long yBalance = 10L;
    private long nuhuh = 20L;

    public long getTotal() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException{
        long result = 0L;
        for(Field field : this.getClass().getDeclaredFields()){
            if(field.getName().endsWith("Balance")){
                result += (long) field.get(this);
            }
        }
        return result;
    }

    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
        System.out.println(new Test().getTotal());
    }
}

Output

15

This doesn't care about types though: if you'd have an integer that ends with Balance, it'd throw an exception. You can always add code to look out for that.

Then again, you could just create a collection and store everything in there:

class Test {
    private Map<String, Long> myBalances = new HashMap<>();

    {
       myBalances.put("savings", 500L);
    }

    public long getSavingsBalance(){
      return myBalances.get("savings");
    }

    public long getTotal(){
      long result = 0L;
      for(long value : myBalances.values()){
         result += value;
      }
      return result;
    }
}
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
  • That's pretty impressive. Thanks for showing me how to refer to field names; since everything does end with Balance I can definitely work it out this way. – Ivan Nov 14 '13 at 03:52
  • @JeroenVannevel Using reflection in this way seems like extraordinarily bad practice. It requires all subsequent developers to be aware of a naming convention they're likely not looking for. If I extend this class and add a "visa" or "loan" I've got to ensure that I override total(). What if I actually USE his naming convention and, because it seems so obvious, override total() to add my values to the mix? OH NO Double count! – InfernalRapture Nov 14 '13 at 03:59
  • @InfernalRapture: it is something that has to be clearly documented, definitely, but I think it's within the boundaries of what's acceptable. You cannot prevent every developer's misconceptions, some parts of the code just might be tricky. That being said: I did offer an alternative route which I would prefer as well. – Jeroen Vannevel Nov 14 '13 at 04:05
  • @JeroenVannevel Sorry, but I'm afraid I disagree. total() seems so intuitive in behaviour I don't know if I'd read that JavaDoc and I can say with a great deal of certainty that a significant portion of my co-workers couldn't be trusted to. It's a convention that's unnecessary and there are more intuitive solutions that don't require future developers to be aware of a convention. As such I'd argue that's not an acceptable solution and if it were to cross my desk in a code-review I'd mandate correction because it could have potentially "dangerous" side-effects. – InfernalRapture Nov 14 '13 at 04:10
  • Reflection is indeed a nono - maintainability, runtime failures, performance etc. Your second solution is much better – Mr_and_Mrs_D Nov 30 '13 at 03:25