• Nick J (unregistered) in reply to c0rnh0li0

    That's nowhere near enterprisey enough for my liking. All the integers should be defined in an external properties file, or maybe an XML file.

    So something like <integers> <integer name="zero">0</integer> <integer name="one">1</integer> <integer name="two">2</integer> <integer name="three">3</integer> ... </integers>

    The XML should be accessible via an IntegerFactory via JNDI Then, to create an int, simply do this:

    Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env");

    // Look up our IntegerFactory IntegerFactory integerFactory = (IntegerFactory) envCtx.lookup("jdbc/IntegerFactory");

    int a = IntegerFactory.lookupInteger(IntegerFactory.FORTY_TWO);

    Simple!

  • (cs) in reply to Jakob Lund Krarup
    Jakob Lund Krarup:
    >Re: The Integer Cache >2010-01-04 10:44 • by Ben >You've made an eggcorn. It's "hare brained", not >"hair brained". As in hare, an animal.

    According to Wikipedia (as I read it, I may be wrong) it is not an EggCorn (where the original meaning is preserved) but a Malapropism (http://en.wikipedia.org/wiki/Eggcorn).

    Kind regards - Jakob

    Nah, I think it's an eggcorn. "has a brain the size of a hair" or "has no brain, just really long-rooted hair that fills their head" (ok, that's a stretch) work. It's no more stupid than a bunch of other phrases. "For all intents and purposes" is just like saying "for all intents and intents", after all, whereas the eggcorn "for all intensive purposes" at least isn't redundant.

  • Bubak (unregistered)

    We are using something simular.

    Reason for this is serialization, it is big difference to have one instance of Integer(0) instead of two millions...

  • PRMan (unregistered) in reply to Bavo
    AFAIK integers below 256 are always cached automatically which makes

    Integer a = new Integer(3); Integer b = new Integer(3); assert a==b;

    succeed, because they will always poijt to the same instance. Typical JCJP gotcha :)

    Integer a = new Integer(300); Integer b = new Integer(300); assert a==b;

    but this will not.

    OK, this is TRWTF.

  • Stiggy (unregistered) in reply to Scott
    Scott:
    The Boolean cache makes the most sense as you only ever need two Boolean objects.

    Three, surely?

    True False FileNotFound

  • anon (unregistered) in reply to PRMan

    MathUtil.getInteger() is similar in concept to Sun's implementation of Integer.valueOf() added in java 1.5:

    public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); }
    MathUtil is surely designed for java 1.4 as autoboxing is not used so this is not a huge WTF IMO.
  • plasma (unregistered)

    I think it's obvious that the coder was just anticipating the possibility that the values of integers will change one day, so that the value of "2" becomes "3". Sure, it would involve the fabric of reality tearing itself apart, but better safe than sorry, right?

  • JB (unregistered) in reply to Daniel Sobral
    Daniel Sobral:
    I hereby declare all of you to be ignorant fools! Change that code and run it with the Java 1.3 it probably came from, and see it crash and burn!!!

    The reason being, of course, that Integer(0) != Integer(0), as reference equality is used for objects. So, unless you cache each boxed Integer you have, you can't rely on them as keys (ParentID, remember?).

    That's assuming that the code referring to it is using == instead of .equals. Since the biggest reason to use wrappers on primitives is to use them in collection objects, most mapping handling would probably be done in standard Map implementations using .equals .compareTo and .hashCode

    .equals may also explain what looks like a tendency to use 0 in place of null: it eliminated the need to check for null before doing comparisons. That part's still bad coding practice, of course, but it does fit.

    The code may be getting compiled in java 6 now but I bet it was originally written in java 1.4 or earlier. If not, the developer probably learned the practice pre-1.5 and never heard about it being added to the language.

  • putate your vul (unregistered) in reply to Crash Magnet
    Crash Magnet:
    And my nomination for best WTF since "Paula Beans".
    My nomination for best comment by "Crash Magnets".
  • Christophe (unregistered) in reply to mr_smith

    Actually, it's a very good idea in case you need to change the value of 0 at a later point int time. Now, you have this single method to fix.

    Hopefully, Java 8 will put this as part of the base language. Some nice syntax like:

    0 := 42; // 0 is just too dangerous

  • Yuck (unregistered) in reply to Christophe

    This is just plain disgusting. It made my eyes bleed. I can't even imagine what went through the head of whatever chimpanzee (or orangutan) wrote this mess. Seriously, WTF?

  • (cs) in reply to cHao
    cHao:
    Jimmy McJimbo:
    but but but... i dont know java... but... if it just returns a pointer to an existing instance of integer, and i then manualy change its value in my code. Wont the value of the original cached object also change, resulting in a tear in the fabric of space and time itself.

    Nope. In Java, Integers are immutable objects. And since they're objects, "changing the value" of an Integer is actually creating (or getting from the/a cache) a whole other Integer and telling your variable to refer to that one instead.

    Ahem You used to be able to modify the Integer.value field using reflection, and you still can if you're willing to hack a bit more (java.lang.Unsafe). Voting machine implementers, take note...


    Submission attempt 2.

  • charlie (unregistered) in reply to The_Assimilator

    In a video game I created in python I used something like

    cos = [ (i, math.cos(i)) for i in range(180)]

    to get cosines, it's much faster to use cos[angle] than math.cos(angle).

  • EvilCodez (unregistered)

    Nobody should be allowed to implement software unless he has proved that he has understood assembler well! I hate wanna be managers coding

  • EvilCodez (unregistered) in reply to charlie

    So did I 20 years ago, because 6502 Processors run at 1 Mhz.

  • (cs) in reply to EvilCodez
    EvilCodez:
    Nobody should be allowed to implement software unless he has proved that he has understood assembler well! I hate wanna be managers coding

    I'll take someone who understands Object-Oriented Design over one who understands assembly any day.

  • Quirkafleeg (unregistered) in reply to EvilCodez
    EvilCodez:
    So did I 20 years ago, because 6502 Processors run at 1 MHz.
    BBC Micro. 6502 (or possibly 65C02 or 6512, depending on model) clocked at 2MHz.
  • burpy (unregistered) in reply to charlie
    charlie:
    In a video game I created in python I used something like
    cos = [ (i, math.cos(i)) for i in range(180)]

    to get cosines, it's much faster to use cos[angle] than math.cos(angle).

    But still, the fastest is to get rid of python...

  • Bosshog (unregistered)

    What's wrong with this? In most computer programs, memory is chock-full of integers. It's nice to see someone trying to address this problem.

  • Charles (unregistered) in reply to Phill
    Phill:
    Ok, so this is stupid but maybe not as stupid as it first seems... He is not caching ints, he's caching the Integer object representation of an int. If he was regularly using loads of Integer objects for values below 256, this might save some memory. As the latest GC implementations optimise towards short lived objects though, I doubt there would be any significant gain, and all for the sake of some horrible code. And I hope he has a good reason for not just using an int as the ParentId - or is Java's nullable int implementation really that bad? (seems like he's using the magic number 0 for null anyway)

    I had to do something very similar to this before the internal integer cache in the jdk (which caches only a limited number of integers anyways).

    We had a reporting application that generated over a dozen graphs per report and many of those graphs had tens of thousands of data points. JFreeChart uses number objects in most of it's methods so we commonly had to convert primitive as well as string values to their Object wrapper counterparts.

    Generating one report would churn through millions of integer objects in a matter of seconds causing serious GC thrashing when trying to generate multiple reports simultaneously (frequent OutOfMemoryErrors was the typical result).

    After running the application profiler it was clear that this was the problem. Using cached integer objects helped enormously (we used a solution that cached the integers with weak references for temporal reuse) and cut down the temporary object churn by several orders of magnitude.

  • Schol-R-LEA (unregistered) in reply to Rick

    Perhaps we should institute the Paula Bean Awards, and give this guy "Worst Attempt At Saving Memory".

  • Rob (unregistered)

    Didn't I just read on stack overflow the other day, that between -128 and 128, Java Integers are cached anyway? CAPTCHA: nulla

  • duder (unregistered) in reply to The_Assimilator

    Python uses cached integers.

    http://docs.python.org/c-api/int.html#PyInt_FromLong

  • Intensive Purpose (unregistered) in reply to Bumble Bee Tuna
    Bumble Bee Tuna:
    Nah, I think it's an eggcorn. "has a brain the size of a hair" or "has no brain, just really long-rooted hair that fills their head" (ok, that's a stretch) work. It's no more stupid than a bunch of other phrases. "For all intents and purposes" is just like saying "for all intents and intents", after all, whereas the eggcorn "for all intensive purposes" at least isn't redundant.

    I always wondered about "Please wait until the ride/bus/train comes to a full and complete stop." What kind of stop would be full but not complete, or vice versa?

  • (cs)

    I think it's fairly obvious by now that either the code was probably part of some general "MathUtil" class that the developer had written years ago and used in all his code, or he just hadn't heard of all the changes in Java 1.5.

    Now, the 2500 line copy pasted method is much, much worse.

  • rb (unregistered) in reply to PK

    We actually did do a integer cache, but we are using python and number are like any other variable. By caching the first 100 integers we got a significant performance increase.

    While the article does sound fishy, it depends on the situation that you are in. for python a number is just another instance of a class so this saved a class allocation with every i += 1

    :)

    but I don't believe Java suffers from this, but don't really know.

  • Suede (unregistered)

    The problem is not what and how he is caching but the fact that he is caching!

    Obviously this is an extreme case of sub optimization. Code like this is most likely to just cost a lot of money due to bugs and just the fact that the lines of code grows, making it more costly to bring new developers into the code base.

    The only reason to have code like this is if there is a serious runtime problem that may only be saved by this type of caching. However, to actually have to optimize a code base to the level of caching integers calls for a total redesign of the system more than actually implementing the cache and think that that would fix the problem.

    /Suede

  • Truthiness (unregistered) in reply to LordOfThePigs

    Integer customerId = 0;

    would of course only be valid if you have access to autoboxing(java5+) otherwise that doesnt even compile..

  • Doug (unregistered)

    The real value of this code is the ability to differentiate between the MathUtil integers and the Integer.valueOf integers. This can allow you to track the code paths that your data has experienced AT RUNTIME.

  • Cbuttius (unregistered)

    If it's used to cache an array of integers then it is fine, eg to use for a non-indexed or clustered sequence (as an index).

    I remember in a previous project where I worked where we had to pass in indexes how frequently we were creating vectors of numbers from 0 to N-1

  • Gallatin (unregistered) in reply to Bavo

    Not correct. In your example both assertions are false because new always creates a new object in java. What you meant was

    Integer a = Integer.valueOf(3); Integer b = Integer.valueOf(3); assert a==b;

    and

    Integer a = Integer.valueOf(300); Integer b = Integer.valueOf(300); assert a==b;

    btw the integers are only cached from -128 up to 127.

  • Saish (unregistered)

    Actually, the source code for java.lang.Integer does the same thing. (Not saying that makes it "right"):

    java.lang.Integer.java (1.6)

    public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }
    
    private static class IntegerCache {
        static final int high;
        static final Integer cache[];
    
        static {
            final int low = -128;
    
            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;
    
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
    
        private IntegerCache() {}
    }
    
  • Zisch (unregistered) in reply to Bavo
    AFAIK integers below 256 are always cached automatically which makes

    Integer a = new Integer(3); Integer b = new Integer(3); assert a==b;

    succeed, because they will always poijt to the same instance. Typical JCJP gotcha :)

    Integer a = new Integer(300); Integer b = new Integer(300); assert a==b;

    but this will not.

    Sorry, not on my Java VM (Sun 1.6.0 on Windows). And I don't think any other Sun Java VM ever did something like this. It would be totally surprising for the programmer and probably violate the language specification.

    I guess before posting code, one should better test it first ... ;-)

  • Matt (unregistered) in reply to The_Assimilator

    Then you've obviously never had a look at Integer.java, or the JLS.

  • Matt (unregistered) in reply to Zisch

    This is a well known Java gotcha... but it relates to autoboxing and goes like this. (and it's in the 8-bit range -128..127 or -XX:AutoBoxCacheMax. See Integer.java)

    Integer a = 3; Integer b = 3; System.out.println(a == b);

    Integer c = 300; Integer d = 300; System.out.println(c == d);

    Should give you: true false

    Surprised ? Take a look at Integer.java, specifically this bit: /** * Returns a Integer instance representing the specified * int value. * If a new Integer instance is not required, this method * should generally be used in preference to the constructor * {@link #Integer(int)}, as this method is likely to yield * significantly better space and time performance by caching * frequently requested values. * * @param i an int value. * @return a Integer instance representing i. * @since 1.5 */ public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); }

    While you might reasonably guess that this would invalidate the language spec, actually reading the spec it would reveal quite the reverse..

  • pl (unregistered) in reply to Randy

    How glad as I when I got the chance to do that!

    In my experience SAP can't even tell you the version number of the library they just sent and told you to use. Ask again a week later and they send you a completely different library. Not just a different version - whatever 'version' might mean that week - but a completely different set of libraries/tools. As for setting up a repeatable install or getting an old install off your machine - forget it. Not even by editing the registry. We had to repeatedly base-line the machine to reinstall SAP. A lot.

    6 months on-and-off, to get some half-arse SAP portal software to display two pages from our app. And it never did work right. What a farce.

    Never, ever, ever use SAP. For anything. Ever.

  • pl (unregistered) in reply to EvilCodez

    Nobody should be allowed to implement software unless he has proved that he has understood Lisp well! I hate wanna be coders managing.

  • mks (unregistered)

    The Real WTF is the language. Given the peculiarities of Java, I revise my judgement of the code from totally stupid to stupid.

    My Judgement of Java is exactly where it had been before.

  • Andrew Pennebaker (unregistered)

    That's actually how Python works. Stupid, but true.

Leave a comment on “The Integer Cache”

Log In or post as a guest

Replying to comment #:

« Return to Article