0

I need to interning string which result of my query. Because my queries first field always contains "0" or "1", and every time its creates new String object. And I want to use intern() on this string and use pool for saving some memory. enter image description here But my statement return a number:

SELECT CASE WHEN b.num >= 12 THEN 1 ELSE 0 END as "result", 
        ROUND (((b.num - 12)/12),2) AS "weight" FROM (SELECT sum(t.amount_inst) AS num 
    FROM MRCH_CARD t 
    ....

So its result in java side was BigDecimal, not String: enter image description here

But inside BigDecimal exists stringCache field with String value, and every time when I call that query as result of exection its creating new String Object with "1" or "0" value. How can I intern() that value to string pool? I tried that way, but I think this didnt work, because qr.getSingleResult() already created new String Object as stringCache field of BigDecimal:

  Object[] tempResult = (Object [])qr.getSingleResult();
  result.setResult(new BigDecimal(tempResult[0].toString().intern()));
  result.setWeight(new BigDecimal(tempResult[1].toString().intern()));
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
MeetJoeBlack
  • 2,804
  • 9
  • 40
  • 66

2 Answers2

0

1) You could modify the SQL query to return a string instead of an integer

2) You could cache ("manually intern") the BigDecimal object itself - by replacing them with the BigDecimal.ONE and BigDecimal.ZERO static cached values

3) The private field stringCache in BigDecinal will be calculated only if you call toString() on the BigDecinal object - but if you need toString(), then you can probably throw away the BigDecinal object

4) (not recommended!) You could call intern even on a private string with reflection, see How do I read a private field in Java?

Community
  • 1
  • 1
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
  • The second option is not necessary IMO. There already are `BigDecimal.ONE` and `BigDecimal.ZERO`, so the OP should use them instead of creating a new `BigDecimal` object every time – BackSlash Dec 30 '14 at 12:55
  • @BackSlash good point, I'll edit the answer. But note that the Op is not creating these objects, they are coming from JDBC – lbalazscs Dec 30 '14 at 13:00
0

A much better solution would be to use the number (int) for the first column. This should work:

 BigDecimal result = resultAsBigDecimal( (Number)tempResult[0] );

 public static BigDecimal resultAsBigDecimal( Number value ) {
     int i = value.intValue();
     if( 0 == i ) return BigDecimal.ZERO;
     if( 1 == i ) return BigDecimal.ONE;
     throw new RuntimException( "Unexpected value: " + value );
 }

intern() for the weight is probably useless. since the weight is going to be many different values.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820