Java >> Java tutorial >  >> Tag >> ArrayList

Liste vs. ArrayList i Java

1. Oversigt

I denne artikel vil vi se på forskellene mellem at bruge Listen og ArrayList typer.

Først vil vi se en eksempelimplementering ved hjælp af ArrayList . Derefter skifter vi til listen interface og sammenlign forskellene.

2. Brug af ArrayList

ArrayList er en af ​​de mest brugte Lister implementeringer i Java. Det er bygget oven på et array, som dynamisk kan vokse og krympe, når vi tilføjer/fjerner elementer. Det er godt at initialisere en liste med en indledende kapacitet, når vi ved, at den bliver stor:

ArrayList<String> list = new ArrayList<>(25);

Ved at bruge ArrayList som referencetype kan vi bruge metoder i ArrayList API, der ikke er på listen API — for eksempel ensureCapacity, trimToSize , eller removeRange .

2.1. Hurtigt eksempel

Lad os skrive en grundlæggende ansøgning om passagerbehandling:

public class ArrayListDemo {
    private ArrayList<Passenger> passengers = new ArrayList<>(20);

    public ArrayList<Passenger> addPassenger(Passenger passenger) {
        passengers.add(passenger);
        return passengers;
    }
    
    public ArrayList<Passenger> getPassengersBySource(String source) {
        return new ArrayList<Passenger>(passengers.stream()
            .filter(it -> it.getSource().equals(source))
            .collect(Collectors.toList()));
    }
    
    // Few other functions to remove passenger, get by destination, ... 
}

Her har vi brugt ArrayList skriv for at gemme og returnere listen over passagerer. Da det maksimale antal passagerer er 20, er den oprindelige kapacitet for listen indstillet til dette.

2.2. Problemet med data med variabel størrelse

Ovenstående implementering fungerer fint, så længe vi ikke behøver at ændre typen af Liste vi bruger. I vores eksempel valgte vi ArrayList og følte, at det opfyldte vores behov.

Lad os dog antage, at efterhånden som applikationen modnes, bliver det klart, at antallet af passagerer varierer ret meget. For eksempel, hvis der kun er fem reserverede passagerer med en initial kapacitet på 20, er hukommelsesspildet 75 %. Lad os sige, at vi beslutter at skifte til en mere hukommelseseffektiv Liste .

2.3. Ændring af implementeringstype

Java giver en anden liste implementering kaldet LinkedList at gemme data i variabel størrelse. LinkedList bruger en samling af sammenkædede noder til at gemme og hente elementer. Hvad hvis vi besluttede at ændre basisimplementeringen fra ArrayList til LinkedList :

private LinkedList<Passenger> passengers = new LinkedList<>();

Denne ændring påvirker flere dele af applikationen, fordi alle funktionerne i demoapplikationen forventer at arbejde med ArrayList type .

3. Skifter til Liste

Lad os se, hvordan vi kan håndtere denne situation ved at bruge Listen grænsefladetype:

private List<Passenger> passengers = new ArrayList<>(20);

Her bruger vi Listen interface som referencetype i stedet for den mere specifikke ArrayList type. Vi kan anvende det samme princip på alle funktionskald og returtyper. For eksempel:

public List<Passenger> getPassengersBySource(String source) {
    return passengers.stream()
        .filter(it -> it.getSource().equals(source))
        .collect(Collectors.toList());
}

Lad os nu overveje den samme problemformulering og ændre basisimplementeringen til LinkedList type. Både ArrayList og LinkedList klasser er implementeringer af Listen interface. Så vi kan nu sikkert ændre basisimplementeringen uden at skabe forstyrrelser i andre dele af applikationen. Klassen kompilerer stadig og fungerer fint som før.

4. Sammenligning af tilgange

Hvis vi bruger en konkret listetype gennem hele programmet, så er al vores kode unødvendigt koblet med den listetype. Dette gør det sværere at ændre listetyper i fremtiden.

Derudover returnerer de hjælpeklasser, der er tilgængelige i Java, den abstrakte type i stedet for den konkrete type. For eksempel returnerer hjælpefunktionerne nedenfor Listen type:

Collections.singletonList(...), Collections.unmodifiableList(...)
Arrays.asList(...), ArrayList.sublist(...)

Specifikt ArrayList.sublist returnerer Listen type, selvom det originale objekt er af ArrayList type. Som sådan metoder i Listen API garanterer ikke at returnere en liste af samme type.

5. Konklusion

I denne artikel undersøgte vi forskellene og bedste praksis ved at bruge List vs ArrayList typer.

Vi så, hvordan henvisning til en bestemt type kan gøre applikationen sårbar over for ændringer på et senere tidspunkt. Specifikt, når den underliggende implementering ændres, påvirker det andre lag af applikationen. Derfor foretrækkes det ofte at bruge den mest abstrakte type (klasse/grænseflade på øverste niveau) frem for at bruge en specifik referencetype.

Som altid er kildekoden til eksemplerne tilgængelig på GitHub.


Java tag