Gyakorlati alapok III.

Leképezés (Map)


Ismételjük meg az egyik előző fejezet legfontosabb megállapításait:

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

A Map legfőbb jellegzetessége, hogy kulcs-érték párokat tartalmaz. 1 kulcs (key) csak 1 értéket (value) azonosíthat be, illetve tiltott a többszörös kulcshasználat (ellenben megengedett a többszörös értékhasználat, természetesen több kulcs esetén).

 

Valós életből vett példák: személyi szám és személynév adatbázisa, ahol kikötés, hogy 1 személyhez csak 1 személyi szám tartozhat (és fordítva).

 

További érdekes Map-példa: ruhatári szituáció, amelyben értékként kezelt ruháinkat a ruhatárnak nevezett tárolóegységbe (kell) tennünk. Az érték azonosítása nem név, hanem egy egyedi kulcs alapján történik (számozott jegy, biléta). Tiltott a többszörös kulcshasználat (ha adott számú biléta többször is előfordul), ám ebben a ruhatári helyzetben 1 kulcshoz rendelhetünk több értéket is (1 biléta, több kabát).

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

Két Map-objektum akkor egyenlő, ha a kulcs-érték párjaik megegyeznek.

A sorrend nem számít.

 

A Map működése alapvetően hasonló a többi, már ismertetett Collection-leszármazotthoz (Set és List), a különbségek főként a kulcs-érték (key-value) páros egyedi jellegzetességeiből és működéséből keletkeznek. A konkrét Java-kódok előtt ellenőrizzük le a Map interfész-implementációját, amelyben észrevehetünk új, specifikus függvényeket:

 

public interface Map {
    V put(K key, V value);
    V get(Object key);
    V remove(Object key);
    boolean containsKey(Object key);
    boolean containsValue(Object value);
    int size();
    boolean isEmpty();
    void putAll(Map<? extends K,? extends V> t);
    void clear();
    public Set<K> keySet();
    public Collection<V> values();
    public Set<Map.Entry<K,V>> entrySet();
    public interface Entry {
    K getKey();
    V getValue();
    V setValue(V value);
    }
}

 

Ezután pedig nézzünk meg néhány futtatható Java-kódon keresztül további, Map-ra jellemző tulajdonságot!

 

Egy Map-objektum létrehozása a megszokottak szerint a következőféleképpen történik:

 

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

 

Kezdeti Map-típusunk tehát a HashMap, amely egyszerű és könnyen kezelhető objektumot ad vissza. Látható, hogy 1 lépésben kell gondoskodnunk a kulcs-értékpár típusainak beállításáról is (itt String és Integer). Az objektum létrehozása után lehetőségünk van azt kulccsal és értékkel feltölteni a put() metódus segítségével:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("Zoltan", 1);
    map.put("Arpad", 2);
    map.put("Bela", 3);
    System.out.println(map);
    }
}
 

Végeredmény:

{Bela=3, Zoltan=1, Arpad=2}

A rendszer bár engedi a duplikált vagy többszörös kulcs-értékpár tartalmat, de ezen, azonos elemekre külön-külön hivatkozni nem lehet. Rákereséskor az első előfordulás fog előbukkanni:

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("Zoltan", 1);
    map.put("Arpad", 2);
    map.put("Bela", 3);
    map.put("Zoltan", 1);
    map.put("Arpad", 2);
    map.put("Bela", 3);
    System.out.println(map);
    }
}
 

Végeredmény:

{Bela=3, Zoltan=1, Arpad=2}
 

Mivel a kereső függvények többsége boolean típusú, a Map esetében szintén true vagy false kimeneti értékkel jelzik, hogy az objektum tartalmazza-e a kulcsot vagy az értéket. Ezt könnyen le tudjuk ellenőrizni a containsKey() és containsValue() függvények segítségével:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("Zoltan", 1);
    map.put("Arpad", 2);
    map.put("Bela", 3);
    map.put("Zoltan", 1);
    map.put("Arpad", 2);
    map.put("Bela", 3);
    System.out.println(map);
    System.out.println(map.containsKey("Zoltan"));
    System.out.println(map.containsValue(1));
    }
}
 

Végeredmény:

{Bela=3, Zoltan=1, Arpad=2}
true
true

 

Most nézzünk meg néhány további függvényt 1 működő Java-kódon belül:

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("Zoltan", 1);
    map.put("Arpad", 2);
    map.put("Bela", 3);
    map.put("Zsolt", 4);
    map.put("Laszlo", 5);
    map.put("Viktor", 6);
    System.out.println(map);
    System.out.println("Az objektum üres? " + map.isEmpty());
    System.out.println("Az objektum mérete: " + map.size());
    map.remove("Viktor", 6);
    System.out.println("Az objektum 'Viktor-6' eltávolítása után: " + map);
    map.replace("Zoltan", 2);
    System.out.println("Az objektum 'Zoltan-1' értékének átállítása után: " + map);
    map.clear();
    System.out.println("Az objektum törlés után: " + map);
    }
}
 

Végeredmény:

{Laszlo=5, Zsolt=4, Viktor=6, Bela=3, Zoltan=1, Arpad=2}
Az objektum üres? false
Az objektum mérete: 6
Az objektum 'Viktor-6' eltávolítása után: {Laszlo=5, Zsolt=4, Bela=3, Zoltan=1, Arpad=2}
Az objektum 'Zoltan-1' értékének átállítása után: {Laszlo=5, Zsolt=4, Bela=3, Zoltan=2, Arpad=2}
Az objektum törlés után: {}

 

Érdemes külön kiemelnünk még 2 további függvényt, amelyek egyszerűen kilistázzák a kulcs-, és és értékhalmazokat (keySet() és values()):

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();
    map.put("Zoltan", 1);
    map.put("Kriszta", 2);
    map.put("Szilvia", 3);
    map.put("Hanna", 4);
    map.put("Arpad", 5);
    map.put("Bela", 6);
    map.put("Peter", 7);
    System.out.println(map.keySet());
    System.out.println(map.values());
    }
}
 

Végeredmény:

[Bela, Zoltan, Szilvia, Arpad, Peter, Hanna, Kriszta]
[6, 1, 3, 5, 7, 4, 2]

 

Most pedig ellenőrizzük le 2 Map-objektum egyenlőségét a már említett állítás alapján:

 

Két Map-objektum akkor egyenlő, ha a kulcs-érték párjaik megegyeznek.

A sorrend nem számít.

 

A létrehozott 2 Map-objektumot ugyanolyan kulcs-értékpárokkal, de különböző beviteli sorrendben töltjük fel:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map1 = new HashMap<>();
    Map<String, Integer> map2 = new HashMap<>();
    map1.put("Zoltan", 1);
    map1.put("Arpad", 2);
    map1.put("Bela", 3);
    map2.put("Arpad", 2);
    map2.put("Zoltan", 1);
    map2.put("Bela", 3);
    if(map1.equals(map2)) {
        System.out.println("A 2 objektum egyenlő.");
    }
    else
        System.out.println("A 2 objektum nem egyenlő.");
    }
}
 

Végeredmény:

A 2 objektum egyenlő.
 

Bármelyik elemet is megváltoztatjuk, a 2 objektum már nem lesz egyenlő:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map1 = new HashMap<>();
    Map<String, Integer> map2 = new HashMap<>();
    map1.put("Zoltan", 1);
    map1.put("Arpad", 2);
    map1.put("Bela", 3);
    map2.put("Arpad", 2);
    map2.put("Zoltan", 1);
    map2.put("Bela", 4);
    if(map1.equals(map2)) {
        System.out.println("A 2 objektum egyenlő.");
    }
    else
        System.out.println("A 2 objektum nem egyenlő.");
    }
}
 

Végeredmény:

A 2 objektum nem egyenlő.
 

Ha már 2 db Map-objektum elénk ugrott, ellenőrizzünk le az egyik tömeges műveletet is (bulk operations). Az alábbi Java-kódban 2 db Map-objektum unióját állítjuk elő egy 3. objektumban:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    Map<String, Integer> map1 = new HashMap<>();
    Map<String, Integer> map2 = new HashMap<>();
    Map<String, Integer> mapEredmeny = new HashMap<>();

    map1.put("Zoltan", 1);
    map1.put("Kriszta", 1);
    map1.put("Szilvia", 2);
    map1.put("Hanna", 3);

    map2.put("Zoltan", 1);
    map2.put("Arpad", 2);
    map2.put("Bela", 3);
    map2.put("Peter", 4);

    mapEredmeny = map1;
    mapEredmeny.putAll(map2);
    System.out.println(mapEredmeny);
    }
}
 

Végeredmény:

{Bela=3, Zoltan=1, Szilvia=2, Arpad=2, Peter=4, Hanna=3, Kriszta=1}
 

Figyeljük meg, hogy szándékosan használunk fel egy duplikált kulcs-értékpárt ("Zoltan", 1), ám az az eredményobjektumban nem duplikálva jelenik meg.

 

A Map természetesen másra is felhasználható. Az alábbi futtatható Java-kódban segítségével szógyakoriságot vizsgálunk:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String args[]) {
    Map<String, Integer> map = new HashMap<String, Integer>();
    String [] bemenetiTomb = {"to", "be", "or", "not", "to", "be"};
    for(int i = 0; i < bemenetiTomb.length; i++) {
        Integer gyakorisag = map.get(bemenetiTomb[i]);
        map.put(bemenetiTomb[i], (gyakorisag == null ? 1 : gyakorisag + 1));
    }
    System.out.println(map.size() + " különböző szó:\n" + map);
    }
}
 

Végeredmény:

4 különböző szó:
{not=1, be=2, or=1, to=2}

 

Látható, hogy a HashMap nem biztosít rendezettséget. A kulcsok betűrendbe állítását a TreeMap képes nekünk elvégezni:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String args[]) {
    Map<String, Integer> map = new TreeMap<String, Integer>();
    String [] bemenetiTomb = {"to", "be", "or", "not", "to", "be"};
    for(int i = 0; i < bemenetiTomb.length; i++) {
        Integer gyakorisag = map.get(bemenetiTomb[i]);
        map.put(bemenetiTomb[i], (gyakorisag == null ? 1 : gyakorisag + 1));
    }
    System.out.println(map.size() + " különböző szó:\n" + map);
    }
}
 

Végeredmény:

4 különböző szó:
{be=2, not=1, or=1, to=2}

 

Ha pedig az eredeti (értsd: az előfordulási) kulcssorrendre vagyunk kíváncsiak, akkor LinkedHashMap-et használjunk:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String args[]) {
    Map<String, Integer> map = new LinkedHashMap<String, Integer>();
    String [] bemenetiTomb = {"to", "be", "or", "not", "to", "be"};
    for(int i = 0; i < bemenetiTomb.length; i++) {
        Integer gyakorisag = map.get(bemenetiTomb[i]);
        map.put(bemenetiTomb[i], (gyakorisag == null ? 1 : gyakorisag + 1));
    }
    System.out.println(map.size() + " különböző szó:\n" + map);
    }
}
 

Végeredmény:

4 különböző szó:
{to=2, be=2, or=1, not=1}