Kaarten in Groovy

1. Overzicht

Groovy breidt het Kaart API in Java naar bieden methoden voor bewerkingen zoals filteren, zoeken en sorteren. Het biedt ook een verschillende steno-manieren om kaarten te maken en te manipuleren.

In dit artikel gaan we kijken naar de manier waarop Groovy met kaarten werkt.

2. Creëren van Groovy Kaarts

We kunnen de letterlijke syntaxis van de kaart gebruiken [k: v] voor het maken van kaarten. In feite stelt het ons in staat om een ​​kaart te instantiëren en items op één regel te definiëren.

Een lege kaart kan worden gemaakt met behulp van:

def emptyMap = [:]

Evenzo kan een kaart met waarden worden geïnstantieerd met behulp van:

def map = [naam: "Jerry", leeftijd: 42, stad: "New York"]

Let erop dat de toetsen zijn niet omgeven door aanhalingstekens.

En standaard maakt Groovy een instantie van java.util.LinkedHashMap. We kunnen dit standaardgedrag opheffen door de net zo operator.

3. Items toevoegen

Laten we beginnen met het definiëren van een kaart:

def map = [naam: "Jerry"]

We kunnen een sleutel aan de kaart toevoegen:

kaart ["leeftijd"] = 42

Maar een andere, meer Javascript-achtige manier is het gebruik van eigenschapnotatie (de puntoperator):

map.city = "New York"

Met andere woorden, Groovy ondersteunt toegang tot sleutel-waardeparen op een boonachtige manier.

We kunnen ook variabelen gebruiken in plaats van literals als sleutels bij het toevoegen van nieuwe items aan de kaart:

def hobbyLiteral = "hobby" def hobbyMap = [(hobbyLiteral): "Singing"] map.putAll (hobbyMap) assertTrue (hobbyMap.hobby == "Singing") assertTrue (hobbyMap [hobbyLiteral] == "Singing")

Eerst moeten we een nieuwe variabele maken waarin de sleutel wordt opgeslagen hobby. Vervolgens gebruiken we deze variabele tussen haakjes met de letterlijke syntaxis van de kaart om een ​​andere kaart te maken.

4. Items ophalen

De letterlijke syntaxis of de eigenschapnotatie kan worden gebruikt om items van een kaart op te halen.

Voor een kaart gedefinieerd als:

def map = [naam: "Jerry", leeftijd: 42, stad: "New York", hobby: "Singing"]

We kunnen de waarde krijgen die overeenkomt met de sleutel naam:

assertTrue (map ["name"] == "Jerry")

of

assertTrue (map.name == "Jerry")

5. Items verwijderen

We kunnen elk item van een kaart verwijderen op basis van een sleutel met behulp van de verwijderen() methode. Maar, soms moeten we mogelijk meerdere vermeldingen van een kaart verwijderen. Dit kan gedaan worden met de minus() methode.

De minus() methode accepteert een Kaart. En retourneert een nieuw Kaart na het verwijderen van alle vermeldingen van de gegeven kaart van de onderliggende kaart:

def map = [1:20, a: 30, 2:42, 4:34, ba: 67, 6:39, 7:49] def minusMap = map.minus ([2:42, 4:34]); assertTrue (minusMap == [1:20, a: 30, ba: 67, 6:39, 7:49])

Vervolgens kunnen we ook vermeldingen verwijderen op basis van een voorwaarde. Dit kan worden bereikt met behulp van de Verwijder alles() methode:

minusMap.removeAll {it -> it.key instanceof String} assertTrue (minusMap == [1:20, 6:39, 7:49])

Omgekeerd, om alle vermeldingen te behouden die aan een voorwaarde voldoen, kunnen we de behoudenAll () methode:

minusMap.retainAll {it -> it.value% 2 == 0} assertTrue (minusMap == [1:20])

6. Itereren door inzendingen

We kunnen items herhalen met behulp van de elk()en eachWithIndex () methoden.

De elk() methode biedt impliciete parameters zoals binnenkomst, sleutel, en waarde die overeenkomen met de huidige Binnenkomst.

De eachWithIndex () methode biedt ook een index naast Binnenkomst. Beide methoden accepteren een Sluiting als argument.

In het volgende voorbeeld herhalen we elk Binnenkomst. De Sluiting doorgegeven aan de elk() methode haalt het sleutel / waarde-paar uit de impliciete parameterinvoer en drukt het af:

map.each {entry -> println "$ entry.key: $ entry.value"}

Vervolgens gebruiken we de eachWithIndex () methode om de huidige index samen met andere waarden af ​​te drukken:

map.eachWithIndex {entry, i -> println "$ i $ entry.key: $ entry.value"}

Het is ook mogelijk om het sleutel, waarde, en index worden apart geleverd:

map.eachWithIndex {sleutel, waarde, i -> println "$ i $ key: $ waarde"}

7. Filteren

We kunnen de find (), findAll () en grep () methoden om kaartvermeldingen te filteren en te zoeken op basis van sleutels en waarden.

Laten we beginnen met het definiëren van een kaart om deze methoden uit te voeren op:

def map = [naam: "Jerry", leeftijd: 42, stad: "New York", hobby: "Singing"]

Eerst kijken we naar de vind() methode die een Sluiting en geeft de eerste terug Binnenkomst die overeenkomt met de Sluiting staat:

assertTrue (map.find {it.value == "New York"}. key == "city")

Evenzo vind alle accepteert ook een Sluiting maar retourneert een Kaart met alle sleutel / waarde-paren die voldoen aan de voorwaarde in het Sluiting:

assertTrue (map.findAll {it.value == "New York"} == [stad: "New York"])

Als we liever een Lijst, we kunnen echter wel gebruiken grep in plaats van vind alle:

map.grep {it.value == "New York"}. elk {it -> assertTrue (it.key == "city" && it.value == "New York")}

We hebben grep eerst gebruikt om inzendingen te vinden die de waarde New York hebben. Om vervolgens aan te tonen dat het retourtype is Lijst, we herhalen het resultaat van grep (). En voor elk Binnenkomst in de lijst die beschikbaar is in de impliciete parameter, controleren we of dit het verwachte resultaat is.

Vervolgens om erachter te komen of alle items op een kaart voldoen aan een voorwaarde die we kunnen gebruiken elke wat een boolean.

Laten we eens kijken of alle waarden op de kaart van het type zijn Draad:

assertTrue (map.every {it -> it.value instanceof String} == false)

Evenzo kunnen we gebruiken ieder om te bepalen of items op de kaart overeenkomen met een voorwaarde:

assertTrue (map.any {it -> it.value instanceof String} == true)

8. Transformeren en verzamelen

Soms willen we de vermeldingen op een kaart omzetten in nieuwe waarden. De ... gebruiken verzamelen() en collectEntries () methoden is het mogelijk om items om te zetten en te verzamelen in een Verzameling of Kaart respectievelijk.

Laten we eens kijken naar enkele voorbeelden.

Gegeven een kaart met werknemers-ID's en werknemers:

def map = [1: [naam: "Jerry", leeftijd: 42, stad: "New York"], 2: [naam: "Long", leeftijd: 25, stad: "New York"], 3: [naam : "Dustin", leeftijd: 29, stad: "New York"], 4: [naam: "Dustin", leeftijd: 34, stad: "New York"]]

We kunnen de namen van alle medewerkers verzamelen in een lijst met verzamelen():

def names = map.collect {entry -> entry.value.name} assertTrue (names == ["Jerry", "Long", "Dustin", "Dustin"])

Als we vervolgens geïnteresseerd zijn in een unieke reeks namen, kunnen we de verzameling specificeren door een Verzameling voorwerp:

def uniqueNames = map.collect ([] as HashSet) {entry -> entry.value.name} assertTrue (uniqueNames == ["Jerry", "Long", "Dustin"] als Set)

Als we de namen van de werknemers op de kaart willen veranderen van kleine letters naar hoofdletters, kunnen we gebruiken collectEntries. Deze methode retourneert een kaart met getransformeerde waarden:

def idNames = map.collectEntries {sleutel, waarde -> [sleutel, waarde.name]} assertTrue (idNames == [1: "Jerry", 2: "Long", 3: "Dustin", 4: "Dustin"] )

Ten slotte, het is ook mogelijk om verzamelen methoden in combinatie met de vind en vind alle methoden om de gefilterde resultaten te transformeren:

def below30Names = map.findAll {it.value.age value.name} assertTrue (below30Names == ["Long", "Dustin"])

Hier vinden we eerst alle medewerkers tussen de 20 en 30 jaar en verzamelen deze op een kaart.

9. Groeperen

Soms willen we sommige items van een kaart groeperen in submaps op basis van een voorwaarde.

De groupBy () methode retourneert een kaart met kaarten. En elke kaart bevat sleutel-waardeparen die voor de gegeven voorwaarde tot hetzelfde resultaat leiden:

def map = [1:20, 2:40, 3: 11, 4: 93] def subMap = map.groupBy {it.value% 2} assertTrue (subMap == [0: [1:20, 2:40] , 1: [3:11, 4:93]])

Een andere manier om submaps te maken, is door subMap (). Het is anders in groupBy () in die zin dat het alleen groeperen toestaat op basis van de sleutels:

def keySubMap = map.subMap ([1,2]) assertTrue (keySubMap == [1:20, 2:40])

In dit geval worden de items voor sleutel 1 en 2 teruggestuurd in de nieuwe kaart en worden alle andere items verwijderd.

10. Sorteren

Meestal willen we bij het sorteren de items in een kaart sorteren op basis van sleutel of waarde of beide. Groovy biedt een soort() methode die voor dit doel kan worden gebruikt.

Gegeven een kaart:

def map = [ab: 20, a: 40, cb: 11, ba: 93]

Als het sorteren op sleutel moet worden gedaan, gebruikt u de no-args soort() methode die is gebaseerd op natuurlijke ordening:

def natuurlijkOrderedMap = map.sort () assertTrue ([a: 40, ab: 20, ba: 93, cb: 11] == natuurlijkOrderedMap)

Of gebruik de sort (vergelijker) methode om vergelijkingslogica te bieden:

def compSortedMap = map.sort ({k1, k2 -> k1 k2} als vergelijker) assertTrue ([a: 40, ab: 20, ba: 93, cb: 11] == compSortedMap)

De volgende, om te sorteren op sleutel of waarden of beide, kunnen we een Sluiting voorwaarde aan soort():

def cloSortedMap = map.sort ({it1, it2 -> it1.value it1.value}) assertTrue ([cb: 11, ab: 20, a: 40, ba: 93] == cloSortedMap)

11. Conclusie

We zijn begonnen met te kijken hoe we kunnen creëren Kaarts in Groovy. Vervolgens hebben we gekeken naar verschillende manieren waarop items kunnen worden toegevoegd, opgehaald en verwijderd van een kaart.

Later hebben we de methoden besproken om veelvoorkomende bewerkingen uit te voeren die standaard in Groovy worden geleverd. Ze omvatten filteren, zoeken, transformeren en sorteren.

Zoals altijd zijn de voorbeelden die in het artikel worden behandeld, te vinden op GitHub.