Struttura Dati Stack in Java
Uno Stack è una struttura dati che segue il principio Last In, First Out (LIFO). Lo stesso principio si applica a un Deque, che hai già incontrato in precedenza, e gli sviluppatori Java raccomandano di utilizzare un Deque quando una struttura dati deve operare secondo il principio LIFO. La struttura dati Stack è obsoleta e non raccomandata nello sviluppo Java moderno.
Tuttavia, alcune collezioni non sono più raccomandate e sono state deprecate.
Deprecato
Quando un elemento viene contrassegnato come deprecato, significa che gli autori della libreria o del linguaggio di programmazione consigliano di evitarne l'uso nel nuovo codice e raccomandano di adottare nuovi metodi, classi o approcci che possano offrire soluzioni più sicure, efficienti o funzionali.
Un esempio è la classe Vector in Java. I suoi metodi sono stati deprecati a favore di collezioni più moderne come ArrayList e LinkedList. Se un programmatore utilizza ancora i metodi di Vector, il compilatore potrebbe emettere un avviso che questi metodi sono deprecati.
Esempio in Java:
Main.java
12345678910111213141516package com.example; import java.util.Vector; public class Main { public static void main(String[] args) { Vector<String> vector = new Vector<>(); // Adding an element (this method is deprecated) vector.addElement("Item"); // Compiler warning about the deprecated method // Note: 'addElement(java.lang.Object)' is deprecated. System.out.println(vector.get(0)); } }
Pertanto, non è consigliato utilizzare una struttura dati come Stack, ma la discuteremo in questo capitolo perché è una struttura dati interessante utilizzata, ad esempio, nella memoria Stack di Java.
Stack
In sintesi, esaminiamo i metodi della classe Stack:
Metodi
push(E element): aggiunge un elemento in cima allo stack.
Main.java
123456789101112package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); } }
L'aggiunta viene eseguita nello stesso modo di ArrayList, quindi analizziamo subito questo metodo in combinazione con il metodo pop():
pop(): rimuove e restituisce l'elemento dalla cima dello stack.
Main.java
1234567891011121314package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); stack.pop(); System.out.println("Stack after the `pop()` method: " + stack); } }
Questo metodo rimuove un elemento dalla cima dello stack. Si noti che il metodo pop() rimuove l'ultimo elemento aggiunto allo stack. Questo è esattamente il funzionamento del principio LIFO.
È anche possibile visualizzare quale elemento si trova in cima allo stack:
peek(): restituisce l'elemento dalla cima dello stack senza rimuoverlo.
Main.java
123456789101112131415package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); String top = stack.peek(); System.out.println("Top element of the stack: " + top); System.out.println("Stack after the `peek()` method: " + stack); } }
Con questo metodo, si osserva l'elemento in cima allo stack.
Utilizzo
Consideriamo un esempio di utilizzo della struttura dati Stack per la navigazione tra le pagine in un browser (quelle frecce avanti e indietro che si usano frequentemente).
Pianifichiamo l'implementazione della cronologia del browser e implementiamo i metodi per due pulsanti (goBack() e goForward()).
Se non è chiaro a quali pulsanti ci si riferisce, si tratta di questi pulsanti di navigazione:
Implementazione di una classe con metodi per gestire questi due pulsanti utilizzando la struttura dati Stack.
Funzionamento
Saranno presenti due stack e una variabile String. Il primo stack memorizza i link visitati tramite il clic sulla freccia "indietro". Il secondo stack memorizza i link visitati tramite il clic sulla freccia "avanti". Una variabile String memorizza il link della pagina corrente.
In questa classe saranno presenti quattro metodi: visitPage(), goBack(), goForward() e getCurrentPage(). Analisi dettagliata di ciascun metodo.
Il metodo visitPage() reindirizza all'URL specificato come parametro. Quando si passa a una nuova pagina, il vecchio link viene aggiunto al backStack. Il forwardStack viene svuotato durante la navigazione verso una nuova pagina.
Di seguito l'implementazione nel codice:
BrowserHistory.java
1234567891011121314151617181920212223242526import java.util.Stack; public class BrowserHistory { private Stack<String> backStack; private Stack<String> forwardStack; private String currentUrl; public BrowserHistory() { backStack = new Stack<>(); forwardStack = new Stack<>(); currentUrl = "https://codefinity.com/profile/my-home"; } public void visitPage(String url) { // When visiting a new page, add the current page to the "back" stack backStack.push(currentUrl); // Reset the "forward" stack as we moved to a new page forwardStack.clear(); // Set the current page to the new URL currentUrl = url; System.out.println("Visited page: " + url); } }
In questo modo è possibile tornare alla pagina precedente durante la navigazione verso una nuova pagina.
Implementazione del metodo per tornare indietro. Funzionamento: si aggiunge il link corrente al forwardStack, quindi si rimuove questo link dal backStack e lo si assegna a currentUrl.
Di seguito l'implementazione nel codice:
BrowserHistory.java
12345678910public void goBack() { if (!backStack.isEmpty()) { // Navigate to the previous page, move from the backStack to the forwardStack forwardStack.push(currentUrl); currentUrl = backStack.pop(); System.out.println("Went back to: " + currentUrl); } else { System.out.println("Cannot go back. Already at the beginning."); } }
Ricorda che il metodo pop() rimuove l'elemento dalla cima dello stack e lo restituisce. Pertanto, utilizzando questo metodo, assegniamo immediatamente il valore dell'URL alla variabile currentUrl.
Verifichiamo inoltre che backStack non sia vuoto; altrimenti, non sarà possibile tornare al link precedente (semplicemente perché non esisterà). Se lo stack è vuoto, viene visualizzato un messaggio corrispondente.
Allo stesso modo, implementiamo il metodo per la navigazione alla pagina successiva. Semplicemente scambiamo gli elementi nello stack:
BrowserHistory.java
12345678910public void goForward() { if (!forwardStack.isEmpty()) { // Navigate to the next page, move from the forwardStack to the backStack backStack.push(currentUrl); currentUrl = forwardStack.pop(); System.out.println("Went forward to: " + currentUrl); } else { System.out.println("Cannot go forward. Already at the latest page."); } }
Ora, tutto ciò che resta è implementare il metodo getCurrentPage(), che restituirà semplicemente il valore di currentUrl.
Verifica
Successivamente, si procede alla verifica di tutto questo nel metodo main. Il metodo visitPage() verrà utilizzato tre volte per assicurarsi che questi collegamenti vengano salvati nella cronologia. Poi, il metodo goBack() verrà utilizzato due volte, seguito dal metodo goForward() una volta, per verificare la funzionalità dei metodi scritti.
Durante questo processo, lo stato verrà monitorato utilizzando il metodo getCurrentPage(). È possibile eseguire il codice sottostante e anche provare a inserire altri collegamenti e utilizzare diversi metodi per testare la funzionalità di questa classe:
Main.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778package com.example; import java.util.Stack; class Main { public static void main(String[] args) { BrowserHistory browser = new BrowserHistory(); System.out.println("Default page: " + browser.getCurrentPage()); browser.visitPage("https://codefinity.com/courses/tracks/7dfbcd35-5cde-49d3-80f1-bf1096487903"); browser.visitPage("https://codefinity.com/courses/v2/8204075c-f832-4cb9-88b1-4e24e74ebdcb/bb00e195-715e-477d-8927-964e6e27cf16/e66c57b4-5f36-43b2-bd3b-e1398044fcab"); browser.visitPage("https://codefinity.com/courses/v2/8204075c-f832-4cb9-88b1-4e24e74ebdcb/bb00e195-715e-477d-8927-964e6e27cf16/1585fb29-47cd-47a6-9fb3-5b391cad24e0"); System.out.println("Current Page after visiting 3 pages: " + browser.getCurrentPage()); browser.goBack(); browser.goBack(); System.out.println("Current Page after going back 2 times: " + browser.getCurrentPage()); browser.goForward(); System.out.println("Current Page after going forward: " + browser.getCurrentPage()); } } class BrowserHistory { private Stack<String> backStack; private Stack<String> forwardStack; private String currentUrl; public BrowserHistory() { backStack = new Stack<>(); forwardStack = new Stack<>(); currentUrl = "https://codefinity.com/profile/my-home"; } public void visitPage(String url) { // When visiting a new page, add the current page to the "back" stack backStack.push(currentUrl); // Reset the "forward" stack as we moved to a new page forwardStack.clear(); // Set the current page to the new URL currentUrl = url; System.out.println("Visited page: " + url); } public void goBack() { if (!backStack.isEmpty()) { // Navigate to the previous page, move from the backStack to the forwardStack forwardStack.push(currentUrl); currentUrl = backStack.pop(); System.out.println("Went back to: " + currentUrl); } else { System.out.println("Cannot go back. Already at the beginning."); } } public void goForward() { if (!forwardStack.isEmpty()) { // Navigate to the next page, move from the forwardStack to the backStack backStack.push(currentUrl); currentUrl = forwardStack.pop(); System.out.println("Went forward to: " + currentUrl); } else { System.out.println("Cannot go forward. Already at the latest page."); } } public String getCurrentPage() { return currentUrl; } }
Ricorda che la classe Stack è obsoleta e non consigliata per l'uso nello sviluppo moderno in Java. È preferibile utilizzare Deque, che rappresenta un'alternativa più efficiente. In questo esempio, Stack viene implementata secondo il principio LIFO, ma è possibile implementare anche Deque, in quanto si tratta di una coda a doppia estremità che supporta sia i principi FIFO che LIFO.
1. Qual è il principio fondamentale di una struttura dati Stack?
2. Qual è il metodo utilizzato per aggiungere un elemento in cima allo stack in Java?
3. Quale delle seguenti collezioni Java è considerata un'alternativa più moderna a Stack?
4. In Java, cosa restituirà il metodo pop() di uno Stack?
Grazie per i tuoi commenti!
Chieda ad AI
Chieda ad AI
Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione
What are the main differences between Stack and Deque in Java?
Can you show how to implement the same browser history example using Deque?
Why is Stack considered obsolete in Java?
Fantastico!
Completion tasso migliorato a 4
Struttura Dati Stack in Java
Scorri per mostrare il menu
Uno Stack è una struttura dati che segue il principio Last In, First Out (LIFO). Lo stesso principio si applica a un Deque, che hai già incontrato in precedenza, e gli sviluppatori Java raccomandano di utilizzare un Deque quando una struttura dati deve operare secondo il principio LIFO. La struttura dati Stack è obsoleta e non raccomandata nello sviluppo Java moderno.
Tuttavia, alcune collezioni non sono più raccomandate e sono state deprecate.
Deprecato
Quando un elemento viene contrassegnato come deprecato, significa che gli autori della libreria o del linguaggio di programmazione consigliano di evitarne l'uso nel nuovo codice e raccomandano di adottare nuovi metodi, classi o approcci che possano offrire soluzioni più sicure, efficienti o funzionali.
Un esempio è la classe Vector in Java. I suoi metodi sono stati deprecati a favore di collezioni più moderne come ArrayList e LinkedList. Se un programmatore utilizza ancora i metodi di Vector, il compilatore potrebbe emettere un avviso che questi metodi sono deprecati.
Esempio in Java:
Main.java
12345678910111213141516package com.example; import java.util.Vector; public class Main { public static void main(String[] args) { Vector<String> vector = new Vector<>(); // Adding an element (this method is deprecated) vector.addElement("Item"); // Compiler warning about the deprecated method // Note: 'addElement(java.lang.Object)' is deprecated. System.out.println(vector.get(0)); } }
Pertanto, non è consigliato utilizzare una struttura dati come Stack, ma la discuteremo in questo capitolo perché è una struttura dati interessante utilizzata, ad esempio, nella memoria Stack di Java.
Stack
In sintesi, esaminiamo i metodi della classe Stack:
Metodi
push(E element): aggiunge un elemento in cima allo stack.
Main.java
123456789101112package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); } }
L'aggiunta viene eseguita nello stesso modo di ArrayList, quindi analizziamo subito questo metodo in combinazione con il metodo pop():
pop(): rimuove e restituisce l'elemento dalla cima dello stack.
Main.java
1234567891011121314package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); stack.pop(); System.out.println("Stack after the `pop()` method: " + stack); } }
Questo metodo rimuove un elemento dalla cima dello stack. Si noti che il metodo pop() rimuove l'ultimo elemento aggiunto allo stack. Questo è esattamente il funzionamento del principio LIFO.
È anche possibile visualizzare quale elemento si trova in cima allo stack:
peek(): restituisce l'elemento dalla cima dello stack senza rimuoverlo.
Main.java
123456789101112131415package com.example; import java.util.Stack; public class Main { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.push("One"); stack.push("Two"); System.out.println("Stack: " + stack); String top = stack.peek(); System.out.println("Top element of the stack: " + top); System.out.println("Stack after the `peek()` method: " + stack); } }
Con questo metodo, si osserva l'elemento in cima allo stack.
Utilizzo
Consideriamo un esempio di utilizzo della struttura dati Stack per la navigazione tra le pagine in un browser (quelle frecce avanti e indietro che si usano frequentemente).
Pianifichiamo l'implementazione della cronologia del browser e implementiamo i metodi per due pulsanti (goBack() e goForward()).
Se non è chiaro a quali pulsanti ci si riferisce, si tratta di questi pulsanti di navigazione:
Implementazione di una classe con metodi per gestire questi due pulsanti utilizzando la struttura dati Stack.
Funzionamento
Saranno presenti due stack e una variabile String. Il primo stack memorizza i link visitati tramite il clic sulla freccia "indietro". Il secondo stack memorizza i link visitati tramite il clic sulla freccia "avanti". Una variabile String memorizza il link della pagina corrente.
In questa classe saranno presenti quattro metodi: visitPage(), goBack(), goForward() e getCurrentPage(). Analisi dettagliata di ciascun metodo.
Il metodo visitPage() reindirizza all'URL specificato come parametro. Quando si passa a una nuova pagina, il vecchio link viene aggiunto al backStack. Il forwardStack viene svuotato durante la navigazione verso una nuova pagina.
Di seguito l'implementazione nel codice:
BrowserHistory.java
1234567891011121314151617181920212223242526import java.util.Stack; public class BrowserHistory { private Stack<String> backStack; private Stack<String> forwardStack; private String currentUrl; public BrowserHistory() { backStack = new Stack<>(); forwardStack = new Stack<>(); currentUrl = "https://codefinity.com/profile/my-home"; } public void visitPage(String url) { // When visiting a new page, add the current page to the "back" stack backStack.push(currentUrl); // Reset the "forward" stack as we moved to a new page forwardStack.clear(); // Set the current page to the new URL currentUrl = url; System.out.println("Visited page: " + url); } }
In questo modo è possibile tornare alla pagina precedente durante la navigazione verso una nuova pagina.
Implementazione del metodo per tornare indietro. Funzionamento: si aggiunge il link corrente al forwardStack, quindi si rimuove questo link dal backStack e lo si assegna a currentUrl.
Di seguito l'implementazione nel codice:
BrowserHistory.java
12345678910public void goBack() { if (!backStack.isEmpty()) { // Navigate to the previous page, move from the backStack to the forwardStack forwardStack.push(currentUrl); currentUrl = backStack.pop(); System.out.println("Went back to: " + currentUrl); } else { System.out.println("Cannot go back. Already at the beginning."); } }
Ricorda che il metodo pop() rimuove l'elemento dalla cima dello stack e lo restituisce. Pertanto, utilizzando questo metodo, assegniamo immediatamente il valore dell'URL alla variabile currentUrl.
Verifichiamo inoltre che backStack non sia vuoto; altrimenti, non sarà possibile tornare al link precedente (semplicemente perché non esisterà). Se lo stack è vuoto, viene visualizzato un messaggio corrispondente.
Allo stesso modo, implementiamo il metodo per la navigazione alla pagina successiva. Semplicemente scambiamo gli elementi nello stack:
BrowserHistory.java
12345678910public void goForward() { if (!forwardStack.isEmpty()) { // Navigate to the next page, move from the forwardStack to the backStack backStack.push(currentUrl); currentUrl = forwardStack.pop(); System.out.println("Went forward to: " + currentUrl); } else { System.out.println("Cannot go forward. Already at the latest page."); } }
Ora, tutto ciò che resta è implementare il metodo getCurrentPage(), che restituirà semplicemente il valore di currentUrl.
Verifica
Successivamente, si procede alla verifica di tutto questo nel metodo main. Il metodo visitPage() verrà utilizzato tre volte per assicurarsi che questi collegamenti vengano salvati nella cronologia. Poi, il metodo goBack() verrà utilizzato due volte, seguito dal metodo goForward() una volta, per verificare la funzionalità dei metodi scritti.
Durante questo processo, lo stato verrà monitorato utilizzando il metodo getCurrentPage(). È possibile eseguire il codice sottostante e anche provare a inserire altri collegamenti e utilizzare diversi metodi per testare la funzionalità di questa classe:
Main.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778package com.example; import java.util.Stack; class Main { public static void main(String[] args) { BrowserHistory browser = new BrowserHistory(); System.out.println("Default page: " + browser.getCurrentPage()); browser.visitPage("https://codefinity.com/courses/tracks/7dfbcd35-5cde-49d3-80f1-bf1096487903"); browser.visitPage("https://codefinity.com/courses/v2/8204075c-f832-4cb9-88b1-4e24e74ebdcb/bb00e195-715e-477d-8927-964e6e27cf16/e66c57b4-5f36-43b2-bd3b-e1398044fcab"); browser.visitPage("https://codefinity.com/courses/v2/8204075c-f832-4cb9-88b1-4e24e74ebdcb/bb00e195-715e-477d-8927-964e6e27cf16/1585fb29-47cd-47a6-9fb3-5b391cad24e0"); System.out.println("Current Page after visiting 3 pages: " + browser.getCurrentPage()); browser.goBack(); browser.goBack(); System.out.println("Current Page after going back 2 times: " + browser.getCurrentPage()); browser.goForward(); System.out.println("Current Page after going forward: " + browser.getCurrentPage()); } } class BrowserHistory { private Stack<String> backStack; private Stack<String> forwardStack; private String currentUrl; public BrowserHistory() { backStack = new Stack<>(); forwardStack = new Stack<>(); currentUrl = "https://codefinity.com/profile/my-home"; } public void visitPage(String url) { // When visiting a new page, add the current page to the "back" stack backStack.push(currentUrl); // Reset the "forward" stack as we moved to a new page forwardStack.clear(); // Set the current page to the new URL currentUrl = url; System.out.println("Visited page: " + url); } public void goBack() { if (!backStack.isEmpty()) { // Navigate to the previous page, move from the backStack to the forwardStack forwardStack.push(currentUrl); currentUrl = backStack.pop(); System.out.println("Went back to: " + currentUrl); } else { System.out.println("Cannot go back. Already at the beginning."); } } public void goForward() { if (!forwardStack.isEmpty()) { // Navigate to the next page, move from the forwardStack to the backStack backStack.push(currentUrl); currentUrl = forwardStack.pop(); System.out.println("Went forward to: " + currentUrl); } else { System.out.println("Cannot go forward. Already at the latest page."); } } public String getCurrentPage() { return currentUrl; } }
Ricorda che la classe Stack è obsoleta e non consigliata per l'uso nello sviluppo moderno in Java. È preferibile utilizzare Deque, che rappresenta un'alternativa più efficiente. In questo esempio, Stack viene implementata secondo il principio LIFO, ma è possibile implementare anche Deque, in quanto si tratta di una coda a doppia estremità che supporta sia i principi FIFO che LIFO.
1. Qual è il principio fondamentale di una struttura dati Stack?
2. Qual è il metodo utilizzato per aggiungere un elemento in cima allo stack in Java?
3. Quale delle seguenti collezioni Java è considerata un'alternativa più moderna a Stack?
4. In Java, cosa restituirà il metodo pop() di uno Stack?
Grazie per i tuoi commenti!