Luettelon kääntäminen käänteiseksi Javassa – paikallaan ja poissa paikasta

Tässä lyhyessä opetusohjelmassa opit vaihtamaan luettelon paikoillaan ja poissa Javassa.

Peruuttaminen paikallaan ja poissa paikasta

Kun suoritat toimintoja listoille – kannattaa harkita, tehdäänkö toiminnot paikan päällä (alkuperäiseen objektiin tehdään muutoksia) vai ovatko ne väärässä paikassa (muutokset tehdään kopiossa ja alkuperäisessä kohde on ennallaan).

Jotkut kielet ja kirjastot suosivat erilaisia ​​oletuskäyttäytymistä. Javassa suurin osa käänteisluetteloiden toiminnoista on paikallaan.

Jos tämä on toivomasi käytös – hienoa! Jos ei, sinun kannattaa luoda kopio luettelosta ennen kuin käännät kopion:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List listCopy = new ArrayList(list);

Huomautus: - clone() menetelmä ei luoda syvä kopio. Luettelon luominen käyttämällä new ArrayList(list) ei luoda syvä kopio. Syvien kopioiden luominen ei ole suositeltavaa, ja se on yllättävän vaikeaa tehdä yleisellä tavalla (eikä se ole joissain tapauksissa järkevää luettelon tietotyypeistä riippuen). Tämä ei estä sinua kääntymästä list ja emme on elementtejä listCopy tosin päinvastoin.

Collections.reverse()

- Collections.reverse() menetelmä on tavallinen menetelmä kokoelman kääntämiseen, ja se toimii "puuttuneena" List.reverse() menetelmä. Se kääntää luettelon päinvastaiseksi:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List listCopy = new ArrayList(list);

Collections.reverse(list);

System.out.println(list);     
System.out.println(listCopy); 

Guavan listat.reverse(lista)

Jos käytät Google Guavaa jo projektissasi, voit myös hyödyntää sitä Lists luokka, joka tarjoaa reverse() menetelmä, joka ei lajittele alkuperäistä luetteloa paikalleen, vaan luo kopion ja kumoaa kopion:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List reversedList = Lists.reverse(list);

System.out.println(list);         
System.out.println(reversedList); 

Jos sinulla ei vielä ole sitä, voit lisätä Google Guavan projektiisi Mavenin avulla sisällyttämällä sen riippuvuuden pom.xml tiedosto:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

Tai Gradlen kautta:

implementation group: 'com.google.guava', name: 'guava'

Huomautus: Jos sinulla ei vielä ole Google Guavaa tai et aio käyttää sitä muissa projektin osissa – älä tuo sitä vain tätä toimintoa varten, vaan pysy Collections.reverse() menetelmä. Guava on suuri riippuvuus, ja se on suuri liioittelua käyttää sitä vain tähän operaatioon.

List.add() ja List.remove()

Jos haluat suorittaa muita toimintoja listan kääntämisen lisäksi – voit selata alkuperäistä luetteloa, poistaa elementit lopusta, siirtää ne mielivaltaisella menetelmällä ja lisätä ne takaisin luettelon alkuun:


public static int process(int input) {
    return input;
}

List list = new ArrayList(Arrays.asList(1, 2, 3));

for (int i = 0, j = list.size()-1; i <= j; i++) {
    int lastValue = process(list.remove(j));
    list.add(i, lastValue);
}

System.out.println(list);  

benchmark

Joten mikä on nopein? Tämä riippuu myös siitä, haluatko suorittaa toimenpiteen paikan päällä vai muualla.

In-Place Reversal Benchmark

Vertaataan molempia lähestymistapoja kaikilla kolmella menetelmällä alkaen sopimattomasta:

List list = new Random().ints(100, 1, 11)
                .boxed()
                .collect(Collectors.toList());

int runs = 1000;

long start1 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListCollections(list);
}
long end1 = System.currentTimeMillis();
System.out.println(String.format("Collections.reverse() took: %s miliseconds", end1-start1));

long start2 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListGuava(list);
}
long end2 = System.currentTimeMillis();
System.out.println(String.format("Guava's Lists.reverse() took: %s miliseconds", end2-start2));

long start3 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListManually(list);
}
long end3 = System.currentTimeMillis();
System.out.println(String.format("Manually took: %s miliseconds", end3-start3));

System.out.println("Original list: " + list);

Tämä johtaa:

Collections.reverse() took: 3 miliseconds
Guava's Lists.reverse() took: 4 miliseconds
Manually took: 13 miliseconds
Original list: [6, 7, 9, 7, 2, 5, 4, 1, 3, 2, 2, 6, ...

Tutustu käytännönläheiseen, käytännölliseen Gitin oppimisoppaaseemme, jossa on parhaat käytännöt, alan hyväksymät standardit ja mukana tuleva huijauslehti. Lopeta Git-komentojen googlailu ja oikeastaan oppia se!

Mitä tapahtuu, kun lisäämme elementtien lukumäärän 100:sta 1000:een?

Collections.reverse() took: 9 miliseconds
Guava's Lists.reverse() took: 4 miliseconds
Manually took: 133 miliseconds
Original list: [10, 2, 2, 6, 2, 4, 7, 3, 9, 2, 7, 5, ...

Guava säilyttää 4 ms:n merkin! Manuaalisella lähestymistavalla on huonoin aikamonimutkaisuus, ja se nousi lineaarisesti. Collections.reverse() kärsivät vähemmän skaalautumisesta, mutta Guavan toteutus kärsii vähiten. Muista kuitenkin, että emme kopioi luetteloa manuaalisesti Guava-lähestymistapaa varten. Muuttuuko vertailuarvo, kun hylkäämme ajatuksen "alkuperäisestä" ja "käänteisestä" luettelosta?

Pois-paikasta kääntymisen vertailuarvo

1000 elementillä, joista jokainen toimii luettelon ei-käänteisellä kopiolla (joka jätettiin pois aikamittauksista), kun poistamme manuaalisen kopion jokaisesta menetelmästä ja suoritamme koodin uudelleen:

Collections.reverse() took: 7 miliseconds
Guava's Lists.reverse() took: 3 miliseconds
Manually took: 131 miliseconds
Original list: [6, 8, 10, 7, 3, 8, 7, 1, 1, 9, 5, ...

Guava yhä onnistuu jatkuvasti ylittämään molemmat Collections.reverse() ja manuaalinen lähestymistapa.

Yhteenveto

Tässä lyhyessä oppaassa olet oppinut kääntämään luettelon Java-kielellä, paikoillaan ja poissa, säilyttäen alkuperäisen luettelon toiminnosta. Olemme käyttäneet Collections.reverse() menetelmä, Google Guava's Lists.reverse() menetelmä ja manuaalinen lähestymistapa.

Aikaleima:

Lisää aiheesta Stackabus