[Java] tellertje bijhouden in een Collection

Pagina: 1
Acties:

  • brama
  • Registratie: Februari 2001
  • Niet online
Ik heb een Map van String naar Integer. Die Integer is in principe een tellertje die ik regelmatig wil ophogen. De huidige methode doet zoiets:

Java:
1
2
3
Integer count = map.get(key);
count = new Integer(count.intValue() + 1);
map.put(key, count);


Niet bijzonder efficient, zullen we maar zeggen..

De oplossing (versimpelde weergave) die ik voor ogen heb is:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Counter {
  public Counter(int fInitVal) {
    this.value = fInitVal;
  }

  public int getValue() {
    return this.value;
  }

  public void increase(int fIncreaseVal)  {
    this.value += fIncreaseVal;
  }

  private int value;
}

//..

Counter c = map.get(key);
c.increase(1);


Nou zal dit wel goed werken, maar ik vraag me af of ik niet een veel voor de hand ligggender oplossing mis waarbij ik niet zelf die Counter class hoef te maken?

I mentioned it once, but I think I got away with it.


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 16-04 11:36

pjvandesande

GC.Collect(head);

Java kent toch wel zo iets als:

Java:
1
count++;

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 13-04 23:48

Nick_S

++?????++ Out of Cheese Error

questa schreef op woensdag 11 januari 2006 @ 16:57:
Java kent toch wel zo iets als:

Java:
1
count++;
Helaas werkt dat alleen op de primitieve int en niet op het object Integer. Als je met Java 5 werkt, zou je echter door de autoboxing volgens mij wel op het object Integer de ++ operator aan kunnen roepen.

Met eerdere java versies zul je inderdaad een eigen Counter klasse aan moeten maken of met nieuwe Integers werken. De eerste daarvan heeft voor mij de voorkeur, hoe minder instanties van objecten je aan hoeft te maken hoe beter.

Brama, over je posts hieronder, wil je de volgende keer gebruik maken van de edit knop ipv 2 berichten?

[ Voor 9% gewijzigd door Nick_S op 11-01-2006 17:16 ]

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


  • sys64738
  • Registratie: Oktober 2002
  • Laatst online: 22:41

sys64738

Moderator Foto & Video

Press play on tape

Waarom wil je uberhaupt een Integer die als teller fungeert in een Map opslaan? Je kunt die teller toch ook in een losse int bijhouden (naast je map)? Of heb je iets heel moois bedacht waardoor dit niet zo makkelijk gaat?

[ Voor 4% gewijzigd door sys64738 op 11-01-2006 17:04 ]

Flickr | Photography 101: Skills > Patience > Gear


  • brama
  • Registratie: Februari 2001
  • Niet online
Nick_S schreef op woensdag 11 januari 2006 @ 17:01:
[...]


Helaas werkt dat alleen op de primitieve int en niet op het object Integer. Als je met Java 5 werkt, zou je echter door de autoboxing volgens mij wel op het object Integer de ++ operator aan kunnen roepen.

Met eerdere java versies zul je inderdaad een eigen Counter klasse aan moeten maken of met nieuwe Integers werken. De eerste daarvan heeft voor mij de voorkeur, hoe minder instanties van objecten je aan hoeft te maken hoe beter.
Ah, dat autoboxing is een nuttige tip. Ik gebruik inderdaad java 1.5, maar die nieuwe feature heb ik nog niet onderzocht. Dat zal ik bij deze eens gaan doen :)

I mentioned it once, but I think I got away with it.


  • brama
  • Registratie: Februari 2001
  • Niet online
sys64738 schreef op woensdag 11 januari 2006 @ 17:03:
Waarom wil je uberhaupt een Integer die als teller fungeert in een Map opslaan? Je kunt die teller toch ook in een losse int bijhouden (naast je map)? Of heb je iets heel moois bedacht waardoor dit niet zo makkelijk gaat?
Ik wil juist een mapping bijhouden van woord naar aantal voorkomens. Dus per key een tellertje.

I mentioned it once, but I think I got away with it.


  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 00:14
Nick_S schreef op woensdag 11 januari 2006 @ 17:01:
[...]
Helaas werkt dat alleen op de primitieve int en niet op het object Integer. Als je met Java 5 werkt, zou je echter door de autoboxing volgens mij wel op het object Integer de ++ operator aan kunnen roepen.

Met eerdere java versies zul je inderdaad een eigen Counter klasse aan moeten maken of met nieuwe Integers werken. De eerste daarvan heeft voor mij de voorkeur, hoe minder instanties van objecten je aan hoeft te maken hoe beter.
Het autoboxing is qua implementatie identiek aan een nieuw Integer object aanmaken per mutatie, dus als je veel te tellen hebt, is dat niet echt efficient. Een eigen class object als wrapper om een int heen, desnoods final en zo veel mogelijk methods static is qua geheugengebruik echt niet inefficienter vergeleken met allemaal nieuwe Integer objecten aanmaken. Ook al worden Integer objecten - dacht ik - tegenwoordig gepooled en evt. hergebruikt, zou het me niks verbazen als je eigen Counter class efficienter is.

Wijsheid in deze is om een kleine benchmark te schrijven en het gewoon even te testen, alle code heb je in principe al.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-04 11:08

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nick_S schreef op woensdag 11 januari 2006 @ 17:01:

Helaas werkt dat alleen op de primitieve int en niet op het object Integer. Als je met Java 5 werkt, zou je echter door de autoboxing volgens mij wel op het object Integer de ++ operator aan kunnen roepen.
Nee, een Integer object is immutable. Je kunt 'm dus niet ophogen, je kunt slechts de waarde uitlezen. Iets als map.put(map.get(key) + 1) zal dus wel werken, maar dat maakt het niet minder efficient dan de code van de topicstarter.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Die oplossing met de Counter-class gaat gewoon goed werken.

Als je nog veel meer rauwe snelheid nodig hebt, dan denk ik dat je het beste een eigen Map-implementatie maakt:

De originele versie staat hieronder.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for this key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated.
     * @param value value to be associated with the specified key.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.  A <tt>null</tt> return can
     *         also indicate that the HashMap previously associated
     *         <tt>null</tt> with the specified key.
     */
    public V put(K key, V value) {
    K k = maskNull(key);
        int hash = hash(k);
        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            if (e.hash == hash && eq(k, e.key)) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, k, value, i);
        return null;
    }

Als je nu de regel e.value = value vervangt door e.value++ oid ben je al klaar.

Siditamentis astuentis pactum.


  • brama
  • Registratie: Februari 2001
  • Niet online
Okay, lijkt me duidelijk dat ik niets over het hoofd gezien heb en dat die Counter implementatie inderdaad "the way to go" is. Dat het efficienter is dan oplossingen waarbij continu Integer objecten aangemaakt en opgeruimd worden lijkt me evident.

Bedankt voor de feedback.

I mentioned it once, but I think I got away with it.

Pagina: 1