CodeGym /Java blog /Tilfældig /Kortgrænseflade i Java
John Squirrels
Niveau
San Francisco

Kortgrænseflade i Java

Udgivet i gruppen

Hvad er Java Map Interface

Java Map-grænsefladen er en del af Java Collection-rammen, men den er ikke en undertype af Collection-grænsefladen. Så det opfører sig på en anden måde sammenlignet med f.eks. lister eller andre samlingsobjekter. Hvert element i Map<Nøgle, Værdi> repræsenterer et nøgleværdi-par. Både Nøgle og værdi er nogle objekter. Alle nøgler i et bestemt kort er unikke, mens værdier ikke er det, så de kan duplikeres. Du tænker måske på Map in Java, såsom en slags ordbog eller online-butikskatalog, hvor du kan finde ethvert element ved hjælp af dets unikke indeks. Nøglen er en unik identifikator for værdien i et kort. For eksempel i Map<String, Item> String er et ID for en vare fra onlineshoppen. Ifølge dokumentation har Map de næste undergrænseflader:
    Indbindinger ;
  • Concurrent Map<K,V> ;
  • ConcurrentNavigableMap<K,V> ;
  • LogicalMessageContext ;
  • MessageContext ;
  • Navigable Map<K,V> ;
  • SOAPMessageContext ;
  • Sorteret kort<K,V> .
Og implementerer klasser:
  • Abstrakt kort
  • Egenskaber
  • AuthProvider
  • ConcurrentHashMap
  • ConcurrentSkipListMap
  • EnumMap
  • HashMap
  • Hastbar
  • IdentityHashMap
  • LinkedHashMap
  • PrinterStateReasons
  • Ejendomme
  • Udbyder
  • RenderingTip
  • SimpleBindings
  • TabularDataSupport
  • Trækort
  • UID-standarder
  • WeakHashMap
  • Java AbstractMap er en abstrakt klasse, der implementerer det meste af kortgrænsefladen.
  • Java HashMap er en datastruktur til lagring af nøgle-værdi-par ved hjælp af en hash-tabel.
  • Java TreeMap er en datastruktur til at bruge et træ, altså visning med sorterede nøgler.
  • WeakHashMap til at bruge en hash-tabel med svage taster, vises med værdier, der kan slettes af skraldeopsamleren, hvis de ikke længere bruges.
  • LinkedHashMap er et kort med rækkefølgen af ​​tilføjelse af elementer, tillader iteration i indsættelsesrækkefølgen.
  • EnumMap udvider AbstractMap- klassen til brug med enum-nøgler.
  • IdentityHashMap bruger referenceækvivalenskontrol ved sammenligning af dokumenter, kortlægning med nøgler sammenlignet med ==- operation i stedet for equals()- metoden
Her er vi interesserede i de mest populære implementeringer af Map Interface: HashMap, TreeMap og LinkedHashMap. I øvrigt afhænger rækkefølgen af ​​kortelementer af specifikke implementeringer. Lad os sige, TreeMap og LinkedHashMap har forudsigelig rækkefølge af elementerne, mens HashMap ikke har.

Kortmetoder

De vigtigste funktioner for ethvert kort er indsættelse, fjernelse og søgning af elementer.
  • public Object put(Objektnøgle, Objektværdi) indsætter et element i kortet.
  • public void putAll(Map map) indsætter det angivne kort i kortet.
  • public Object remove(Object key) sletter en post i henhold til den angivne nøgle.
  • public Object get(Objektnøgle) returnerer værdien for den angivne nøgle.
  • public boolean containsKey(Objektnøgle) søger efter den angivne nøgle fra dette kort
  • public Set keySet() returnerer en Set-visning, der indeholder alle nøglerne
  • public Set entrySet() returnerer en Set-visning med alle nøglerne og værdierne.

Hvad er HashMap

Hvad er HashMap? Det er den mest populære implementering af Map<Key,Value>-grænsefladen. Denne datastruktur er baseret på hashing-princippet.

Hovedprincippet i HashMap-arbejdet: hashing

For at forstå, hvad et hashmap er, og hvordan det virker, lad os først tale om hash- og hashfunktioner. En hashfunktion er bare en funktion i matematisk forstand. Så der er en eller anden inputværdi (et objekt, et stykke data), og funktion konverterer den ved hjælp af en korrekt regel til outputværdi - en hash. Ganske ofte er hash et hexadecimalt tal med en passende længde. Reglerne for konverteringsprocesser kan være anderledes, men de er underlagt følgende principper:
  1. Et bestemt input (objekt) har en bestemt hash-kode.
  2. Hvis to objekter er ens, er deres hash-koder også ens. Det omvendte er ikke sandt.
  3. Hvis hash-koderne er forskellige, er objekterne bestemt ikke ens.
  4. Nogle gange kan forskellige objekter have den samme hash-kode. Det er en meget usandsynlig hændelse, kaldet "kollision", og en hash-funktion af god kvalitet bør minimere sandsynligheden for kollisioner.
I Java har hvert objekt en hash-kode. Det beregnes ved hjælp af hashCode-metoden for Object-klassen, forældreklassen for alle Java-objekter. Normalt tilsidesætter udviklere denne metode for deres egne klasser og er lig med metoder forbundet med den.

HashMap: hvordan det virker

Så Class HashMap<K,V>, da enhver kortimplementering består af nøgler og værdier. Det gemmer nøgler ved hjælp af hashing-principper. Inde i HashMap er nøgleværdipar gemt i "buckets", disse buckets konstruerer sammen en "tabel", en intern række af sammenkædede lister og dens oprindelige størrelse er 16. HashMap i Java bruger nøglens hashkode til at bestemme en bucket, hvor nøgle/værdi-parret skal kortlægges: Den vanskelige funktion ved HashMap er, at hver celle (bucket) i tabellen [] holder ikke kun et par, men flere. De gemmes ikke som et eksplicit objekt (som LinkedList), men som en implicit kæde. Kæden er skabt på grund af, at hvert par gemmer et link til det næste par. Det vil sige, at alle HashMap-par er spredt ud over 16 kæder. Når du lægger et nyt par ind i bordet, bliver nøglens hash taget i betragtning. Denne hash er ikke en hashkodefunktion indbygget i nøgleobjektet. Det anses for at være i intervallet 0-15. Parret føjes til kæden af ​​par, der er gemt i bøtten med hash-indekset. Denne tilgang giver os søgeacceleration. Mens du søger efter et par med nøgle, er der ingen grund til at gennemgå hele bordet. Nøglens hash tages i betragtning, og kun den kæde, der er gemt i cellen med hash-indekset, kontrolleres. Hvis der er for mange par i HashMap, bliver kæderne for lange. Derefter øges størrelsen af ​​arrayet, hashen af ​​alle lagrede objekter genberegnes, og de bliver spredt langs nye kæder.

HashMap-erklæring

Hvis du går til klassens HashMap-kode, finder du den næste erklæring:

public class HashMap extends AbstractMap implements Map, Cloneable, Serializable
Hvor K er den type nøgler, der vedligeholdes af dette kort, og V - typen af ​​kortlagte værdier. Dette er et eksempel på HashMap-erklæring med heltalsnøgle og strengværdi i din kode:

HashMap<Integer, String> myHashMap = new HashMap<Integer, String>();

HashMap metoder

Her er listen over HashMap-metoder.
  • Objekt get(Objektnøgle) returnerer værdien for den angivne nøgle;
  • Objekt put(Key k, Værdi v) indsætter nøgleværditilknytning i kortet;
  • Objekt fjern(Objektnøgle) fjerner tilknytningen for den angivne nøgle fra dette kort, hvis det findes;
  • void clear() fjerner alle nøgleværdi-par fra HashMap;
  • Object clone() returnerer en overfladisk kopi af denne HashMap-instans uden at klone nøglerne og værdierne;
  • boolean containsKey(Objektnøgle) returnerer sand, hvis den angivne nøgle findes i kortet, falsk, hvis ikke;
  • boolean containsValue(Object Value) returnerer sand, hvis den angivne nøgle findes i kortet, false, hvis ikke;
  • boolean isEmpty() returnerer sand, hvis kortet er tomt, falsk, hvis det ikke er det;
  • Set keySet() returnerer sættet af nøgler hentet fra kortet;
  • int size() returnerer mængden af ​​nøgleværditilknytning;
  • Collection values() returnerer en samling af kortets værdier;
  • Objekt fjern(Objektnøgle) fjerner nøgleværdi-parret for den angivne nøgle;
  • void putAll(Map m) kopierer alle elementer af kortet til det andet kort.

Java HashMap eksempel

Lad os oprette et program med Java HashMap Eksempel for at demonstrere, hvordan det virker:

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Set;
 
public class HashMap {
 
   public static void main(String[] args) {
 
       {
 
           // HashMap declaration
           HashMap<Integer, String> myHashMap = new HashMap<Integer, String>();
 
           //Adding elements into HashMap
           myHashMap.put(7, "Johnny");
           myHashMap.put(8, "Ivy");
           myHashMap.put(1, "Rick");
           myHashMap.put(4, "Stan");
           myHashMap.put(3, "Kyle");
 
           //print out the map content using Iterator
           Set set = myHashMap.entrySet();
           Iterator iterator = set.iterator();
           while (iterator.hasNext()) {
               Map.Entry mapEntry = (Map.Entry) iterator.next();
               System.out.print("key: " + mapEntry.getKey() + " value: ");
               System.out.println(mapEntry.getValue());
           }
           System.out.println("get an element from myHashMap via key and print the value out:");
           System.out.println(myHashMap.get(8));
           //print out hashMap on standard way:
           System.out.println(myHashMap);
 
           // Get values based on key
           String var = myHashMap.get(2);
           //here we'll get null, we don't have such a key
           System.out.println("Value with key 2: " + var);
           var = myHashMap.get(7);
           System.out.println("Value with key 7: " + var);
 
           // Remove values based on key
           myHashMap.remove(4);
           System.out.println("myHashMap after removing element:");
           System.out.println(myHashMap);
           myHashMap.clear();
           System.out.println("myHashMap after total clearing:");
           System.out.println(myHashMap);
       }
 
   }
}
Resultatet af at køre programmet:

key: 1 value: Rick
key: 3 value: Kyle
key: 4 value: Stan
key: 7 value: Johnny
key: 8 value: Ivy
get an element from myHashMap via key and print the value out:
Ivy
{1=Rick, 3=Kyle, 4=Stan, 7=Johnny, 8=Ivy}
Value with key 2: null
Value with key 7: Johnny
myHashMap after removing element:
{1=Rick, 3=Kyle, 7=Johnny, 8=Ivy}
myHashMap after total clearing:
{}

Trækort

TreeMap i Java implementerer også Map<Key,Value>-grænsefladen, men den er baseret på rød-sort trædatastruktur. Et træ består af "knuder" og linjer, der forbinder noder - grene". "Rod"-knuden er øverst i træet. Fra roden kan der være grene og knudepunkter. Det er en hierarkisk struktur, du måske tænker på disse noder som "børn" af roden. Barneknude kan have sine egne børn - lavere noder. Noder uden børn kaldes "end-nodes" eller "blade". Et binært træ er et træ, hvor hver node har nul, en , eller to børn. Det binære søgetræ er en struktur, hvor hver intern node gemmer en nøgle, og nogle gange en tilhørende værdi, og har to adskilte undertræer ("venstre" og "højre"). Et selvbalancerende binært søgetræ er et nodebaseret binært søgetræ, der automatisk holder sin højde (maksimalt antal niveauer under roden) lille i forhold til vilkårlige elementindsættelser og -sletninger. Et rød-sort træ er et balanceret binært træ med egenskaberne:
  • Hver knude er enten rød eller sort
  • Roden er altid sort
  • Hvert blad er en NIL (en slags tom, null) node, og den er sort
  • Hvis en node er rød, er dens børn helt sikkert sorte.
  • Hver enkel sti fra en node til et efterkommerblad indeholder det samme antal sorte noder.

En TreeMap funktioner

Et TreeMap bruger en trædatastruktur til at gemme nøglerne som noder og sorterer nøglerne ved hjælp af Red-Black Tree-algoritmen. Så TreeMap holder sine poster sorteret efter den naturlige rækkefølge af nøglerne. For tal er naturlig stigende rækkefølge, for strenge - alfabetisk rækkefølge. Du kan bruge en komparator, hvis du skal ændre bestillingslogikken. At sortere objekter på en naturlig måde er en stor fordel ved TreeMap, samt at finde nogle objekter ved hjælp af forskellige filtre og betingelser.

TreeMap metoder

  • Objekt get(Objektnøgle) returnerer værdien af ​​den tilsvarende nøgle;
  • Object put(Objektnøgle, Objektværdi) indsætter en mapping i et kort;
  • Objekt fjern(Objektnøgle) fjerner tilknytningen for denne nøgle fra, hvis trækortet indeholder det;
  • boolean containsKey(Objektnøgle) returnerer sand, hvis dette kort indeholder en mapping for den angivne nøgle;
  • boolean containsValue(Objektværdi) returnerer sand, hvis TreeMap tilknytter en eller flere nøgler til den angivne værdi;
  • Objekt firstKey() returnerer den første nøgle i øjeblikket i det sorterede kort;
  • Objekt lastKey() returnerer den sidste nøgle i øjeblikket i det sorterede kort;
  • void putAll(Map map) kopierer alle mappings fra det specificerede kort til kortet;
  • Set entrySet() returnerer en indstillet visning af tilknytningerne
  • int size() returnerer mængden af ​​nøgleværdi-tilknytninger
  • Collection values() returnerer en samlingsvisning af værdierne
  • Object clone() returnerer en lavvandet kopi af TreeMap
  • void clear() fjerner alle tilknytninger fra trækortet
  • SortedMap headMap(Object key_value) returnerer en visning af den del af kortet, der er mindre end parameteren key_value
  • Set keySet() returnerer en Set-visning af nøglerne indeholdt i træoversigten
  • SortedMap subMap(K fromKey, K toKey) returnerer en visning af den del af dette kort, hvis nøgler spænder fra fromKey, inklusive, til toKey, exclusive
  • Objekt firstKey() returnerer den første nøgle fra TreeMap.

TreeMap eksempel


import java.util.TreeMap;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
 
public class TreeMapExample {
 
   public static void main(String args[]) {
 
       //TreeMap declaration
       TreeMap<Integer, String> myTreeMap = new TreeMap<Integer, String>();
 
       //put elements to TreeMap
       myTreeMap.put(1, "Stuart");
       myTreeMap.put(23, "Michael");
       myTreeMap.put(7, "Johnny");
       myTreeMap.put(5, "Ivy");
       myTreeMap.put(2, "Alex");
 
       //Display and print out myTreeMap using Iterator
       Set set = myTreeMap.entrySet();
       Iterator iterator = set.iterator();
       while (iterator.hasNext()) {
           Map.Entry myEntry = (Map.Entry) iterator.next();
           System.out.print("key: " + myEntry.getKey() + " value: ");
           System.out.println(myEntry.getValue());
       }
       //TreeMap printed in classical way
       System.out.println(myTreeMap);
       //removing an element with the key =2
       myTreeMap.remove(2);
       //myTreeMap after removing:
       System.out.println(myTreeMap);
   }
}
Resultatet af at køre programmet:

key: 1 value: Stuart
key: 2 value: Alex
key: 5 value: Ivy
key: 7 value: Johnny
key: 23 value: Michael
{1=Stuart, 2=Alex, 5=Ivy, 7=Johnny, 23=Michael}
{1=Stuart, 5=Ivy, 7=Johnny, 23=Michael}

LinkedHashMap

LinkedHashMap er en datastruktur, der kombinerer linkede lister og hash-kort. Faktisk udvider LinkedHashMap HashMap-klassen og implementerer Map-grænsefladen, men hvad handler det om sammenkædede lister? Erklæringen fra LinkedHashMap:

Map <Integer, String> linkedHashMap = new LinkedHashMap <Integer, String>();
Dette nye linkedHashMap arver egenskaber fra HashMap (såsom tabel, loadFactor, threshold, size, entrySet), får også to specielle egenskaber:
  • header er hovedet på en dobbelt linket liste. Under initialiseringen indikerer det sig selv
  • accessOrder angiver, hvordan man får adgang til elementer ved hjælp af iterator. Hvis sandt, i rækkefølgen af ​​den sidste adgang. Hvis falsk, vil adgangen være i den rækkefølge, elementerne blev indsat.
Denne sammenkædede liste definerer iterationsrækkefølgen. Normalt er det rækkefølgen af ​​nøgler, der indsættes i kortet.

LinkedHashMap-metoder

  • Objekt get(Objektnøgle) returnerer den værdi, som den angivne nøgle er knyttet til, eller null, hvis dette kort ikke indeholder nogen tilknytning til nøglen
  • void clear() fjerner alle tilknytninger fra kortet.
  • boolean containsKey(Objektnøgle) returnerer sand, hvis det angivne element er kortlagt af en eller flere nøgler
  • boolean removeEldestEntry(Map.Entry eldest) returnerer sand, hvis kortet fjerner sin ældste post fra kortet
  • Set<Map.Entry<K,V>> entrySet() returnerer en Set-visning af tilknytningerne indeholdt i dette kort
  • void forEach(BiConsumer<? super K,? super V> handling) udfører den givne handling for hver post i dette kort, indtil alle poster er blevet behandlet, eller handlingen kaster en undtagelse.
  • Objekt getOrDefault(Objektnøgle, V defaultValue) returnerer den værdi, som den angivne nøgle er knyttet til. Hvis kortet ikke indeholder en tilknytning til nøglen, returnerer standardværdien.
  • Set<K> keySet() returnerer en Set-visning af nøglerne på kortet
  • boolean removeEldestEntry(Map.Entry<K,V>eldest) returnerer sand, hvis dette kort skulle fjerne sin ældste post
  • void replaceAll(BiFunction<? super K,? super V,? udvider V>-funktionen) erstatter hver indtastningsværdi med resultatet af at kalde den givne funktion på den indgang, indtil alle indtastninger er blevet behandlet, eller funktionen afgiver en undtagelse.
  • Collection<v>values() returnerer en samlingsvisning af værdierne på kortet

LinkedHashMap eksempel


import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
   public class HashLinkedListExample {
       public static void main(String args[]) {
           // LinkedHashMap Declaration
           LinkedHashMap<Integer, String> myLinkedHashMap =
                   new LinkedHashMap<Integer, String>();
 
           //Adding elements into LinkedHashMap
           myLinkedHashMap.put(7, "Johnny");
           myLinkedHashMap.put(12, "Rick");
           myLinkedHashMap.put(1, "Kyle");
           myLinkedHashMap.put(5, "Percy");
           myLinkedHashMap.put(85, "Sebastian");
 
           // Generate a Set of entries
           Set set = myLinkedHashMap.entrySet();
 
           // Display and print out the nodes  of LinkedHashMap
           Iterator iterator = set.iterator();
           while(iterator.hasNext()) {
               Map.Entry me = (Map.Entry)iterator.next();
               System.out.print("key: "+ me.getKey() +
                       " value: "+me.getValue()+"\n");
           }
           //print out HashLinkedMap on standard way:
           System.out.println(myLinkedHashMap);
           myLinkedHashMap.put(21, "Ivy");
           System.out.println(myLinkedHashMap);
           myLinkedHashMap.remove(12);
           System.out.println(myLinkedHashMap);
           myLinkedHashMap.put(12, "Ronny");
           System.out.println(myLinkedHashMap);
           myLinkedHashMap.put(1, "Stan");
           System.out.println(myLinkedHashMap);
       }
   }
Her opretter vi et nyt LinkedHashMap, tilføjer fem elementer, og udskriver det derefter ved hjælp af iterator og på en klassisk måde. Som du kan se, vedligeholder LinkedHashMap indsættelsesrækkefølgen. Efter det sletter vi et element fra vores kort, tilføjer derefter det nye og senere - et element mere med nøglen, der allerede er på kortet. Den erstatter den gamle værdi, der er knyttet til denne nøgle. Resultatet af kørende program:

key: 7 value: Johnny
key: 12 value: Rick
key: 1 value: Kyle
key: 5 value: Percy
key: 85 value: Sebastian
{7=Johnny, 12=Rick, 1=Kyle, 5=Percy, 85=Sebastian}
{7=Johnny, 12=Rick, 1=Kyle, 5=Percy, 85=Sebastian, 21=Ivy}
{7=Johnny, 1=Kyle, 5=Percy, 85=Sebastian, 21=Ivy}
{7=Johnny, 1=Kyle, 5=Percy, 85=Sebastian, 21=Ivy, 12=Ronny}
{7=Johnny, 1=Stan, 5=Percy, 85=Sebastian, 21=Ivy, 12=Ronny}

HashMap, TreeMap, LinkedHashMap Sammenligning

HashMap, TreeMap og LinkedHashMap er implementeringer af kortgrænseflader. HashMap og LinkedHashMap er datastrukturer, der hashes nøgler. TreeMap bruger den naturlige rækkefølge af sine nøgler til at organisere et søgetræ. Bestille:
  • HashMap opretholder ikke nogen orden.
  • TreeMap sorterer indtastningerne i stigende rækkefølge af nøgler.
  • LinkedHashMap vedligeholder indsættelsesrækkefølgen.
Nul nøgler:
  • HashMap og LinkedHashMap gør det muligt at have én null-nøgle.
  • LinkedHashMap tillader ikke null-nøgler i tilfælde af, at nøglerne bruger naturlig rækkefølge, eller Comparator understøtter ikke sammenligning på null-leys.
Lad os få et eksempel på et Java-kort, der inkluderer alle tre implementeringer, der er gennemgået i denne artikel:

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;
 
public class CompMapImpl {
 
 
    public static void main(String[] args) {
        HashMap<Integer, String> hashMap = new HashMap<>();
        TreeMap<Integer, String> treeMap = new TreeMap<>();
        LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();
        hashMap.put(5, "Ivy");
        hashMap.put(null, "Joker");
        hashMap.put(1, "First");
        hashMap.put(2, "Kyle");
        hashMap.put(-2, "Paul");
        hashMap.put(3, "Sandy");
 
 
        treeMap.put(5, "Ivy");
        //treeMap.put(null,"Joker");
        treeMap.put(1, "First");
        treeMap.put(2, "Kyle");
        treeMap.put(-2, "Paul");
        treeMap.put(3, "Sandy");
 
        linkedHashMap.put(5, "Ivy");
        linkedHashMap.put(null, "Joker");
        linkedHashMap.put(1, "First");
        linkedHashMap.put(2, "Kyle");
        linkedHashMap.put(-2, "Paul");
        linkedHashMap.put(3, "Sandy");
        System.out.println("HashMap");
        System.out.println(hashMap);
        System.out.println("TreeMap");
        System.out.println(treeMap);
        System.out.println("LinkedHashMap");
        System.out.println(linkedHashMap);
 
 
        LinkedHashMap<String, String> linkedHashMap1= new LinkedHashMap<> ();
        linkedHashMap1.put(null, "Andy");
        System.out.println(linkedHashMap1);
    }
}
Her er resultatet af at køre dette program:

HashMap
{null=Joker, 1=First, -2=Paul, 2=Kyle, 3=Sandy, 5=Ivy}
TreeMap
{-2=Paul, 1=First, 2=Kyle, 3=Sandy, 5=Ivy}
LinkedHashMap
{5=Ivy, null=Joker, 1=First, 2=Kyle, -2=Paul, 3=Sandy}
{null=Andy}
Som vi kan se, er rækkefølgen af ​​elementer i HashMap ikke indlysende, i treeMap afhænger det af nøgler, i LinkedHashMap handler det om indsættelsesrækkefølge. Hvis vi forsøger at sætte null-nøgle i linkedHashMap, får vi NullPointerException, men i linkedHashMap1, hvor nøgler er String, kan vi gøre det. Et hash-kort er den bedste generelle kortimplementering. Det giver maksimal søgehastighed, hurtig lagring og genfindingsoperationer, men du bør huske på dens kaotiske rækkefølge. Et linket hash-kort arver HashMap-fordele og får en ordre på nøglerne. Det indeholder dog linkedList, som er relativt dyrt i forhold til hukommelse. det er langsommere end HashMap i søgning og en lille smule langsommere til tilføje/fjerne på grund af opretholdelse af linkede liste. Et trækort gemmer nøgler sorteret i stigende rækkefølge. Imidlertid, For at styrke det, du har lært, foreslår vi, at du ser en videolektion fra vores Java-kursus
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION