Linked List and Stack - Java Collection Framework

1. Linked list

When you need to dynamically reduce or increase data items, you can use the data structure of linked list

A linked list is a data structure composed of several objects called nodes, each node contains a data and a reference to the next node (single linked list), or contains a data and a reference to the previous node and a reference to the next node (double linked list)

                                               Singly linked list diagram

                                               Schematic diagram of double linked list

LinkedList<E> generic class

The objects created by the LinkedList<E> generic class in the java.util package store data in a linked list structure . It is customary to call the objects created by the LinkedList class a linked list object.

LinkedList<String>mylist = new LinkedList<String>();

Create an empty doubly linked list.

When using the LinkedList<E> generic class to declare and create a linked list, you must specify the specific type of E, and then the linked list can use the add(E obj) method to add nodes to the linked list in turn .

The above linked list mylist uses the add method to add nodes, and the data in the nodes must be String objects.

mylist.add("How");
mylist.add("Are");
mylist.add("You");
mylist.add("Java");

There are 4 nodes in the linked list mylist, and the nodes are automatically linked together, no linking is required. That is to say, there is no need to operate the reference of the next or previous node stored in the arrangement node.

Common methods of ListedList<E> generic class

LinkedList<E> is a generic class that implements the generic interface List<E>, and the generic interface List<E> is a subinterface of the Collection<E> generic interface. Most of the methods in LinkedList<E> generic class are the implementation of generic interface methods.

When programming, you can use the interface callback technology, that is, assign the reference of the LinkedList<E> object to the Collection<E> interface variable or List<E> interface variable, then the interface can call the interface method implemented by the class.

The following are some commonly used methods in the LinkedList<E> generic class implementing the List<E> generic interface.

public boolean add(E element): Add a new node to the end of the linked list, and the data in this node is the data specified by the parameter element.

public void add(int index, E element): Add a new node to the specified position of the linked list, and the data in this node is the data specified by the parameter element.

public void clear(): Delete all the nodes of the linked list, making the current linked list an empty linked list.

public E remove(int index) : Delete the node at the specified position.

public boolean remove(E element): Delete the node that contains data element for the first time.

public E get(int index): Get the data in the node at the specified position in the linked list.
public int indexOf(E element): Returns the position where the node containing the data element appears for the first time in the linked list, or -1 if there is no such node in the linked list.

public int lastIndexOf(E element): Returns the last position of the node containing the data element in the linked list, or -1 if there is no such node in the linked list.

public E set(int index, E element); Replace the data in the node at the index position of the current linked list with the data specified by the parameter element, and return the replaced data.
public int size(): Returns the length of the linked list, that is, the number of nodes.

public boolean contains (Object element): Determine whether any node in the linked list contains data
element.

The following are the newly added common methods of the LinkedList<E> generic class itself

public void addFirst(E element): Add a new node to the head of the linked list
, and the data in the node is the data specified by the parameter element.

public void addLast(E element): Add a new node to the end of the linked list, and the data in this node is the data specified by the parameter elememt.

public E getFirst(): Get the data in the first node in the linked list.

public E getLast(): Get the data in the last node in the linked list.

public E removeFirst(): Delete the first node and return the data in this node.

public E removeLast(): Delete the last node and return the data in this node.

public Object clone(): Obtain a clone linked list of the current linked list,  the change of the node data in the cloned linked list will not affect the data of the nodes in the current linked list .

Traversing the linked list

No matter what kind of collection, customers should be allowed to traverse the objects in the collection in a certain way without knowing how these objects are represented and stored in the collection. The Java collection framework is a collection of various data structures, such as linked lists and hash tables. A collection of different storage structures, such as , provides selectors .

Some collections also provide methods to return data according to their data storage structure and operations. For example, the  get(int index) method in the LinkedList class will return the object in the index node in the current linked list . The storage structure of LinkedList is not a sequential structure, therefore, the speed of calling the get(int index) method of the linked list is slower than the speed of calling the get(int index) method of the collection of the sequential storage structure . Therefore, when users need to traverse the objects in the collection , they should use the selector provided by the collection instead of letting the collection itself traverse the objects in it. Because the method of the selector traversing the collection finds an object in the collection, it also obtains the reference of the successor object to be traversed , so the selector can quickly traverse the collection.

The linked list object can use the iterator() method to obtain an Iterator object , which is the iterator for the current linked list .

The following comparisons use the time it takes to iterate through a linked list and the time it takes to traverse a linked list using the get(int index) method :

import java.util.Iterator;
import java.util.LinkedList;

public class Ex13_3 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LinkedList<String> list = new LinkedList<String>();
		for(int i=0;i<=60096;i++) {
			list.add("speed"+i);
		}
		Iterator<String> iter = list.iterator();
		long starttime = System.currentTimeMillis();
		while(iter.hasNext()) {
			String te = iter.next();
		}
		long endTime = System.currentTimeMillis();
		long result = endTime-starttime;
		System.out.println("使用迭代器遍历集合所用时间:"+result+"毫秒");
		
		starttime=System.currentTimeMillis();
		for(int i=0;i<list.size();i++) {
			String te = list.get(i);
		}
		endTime = System.currentTimeMillis();
		result = endTime - starttime;
		System.out.println("使用get方法遍历集合所用时间:"+result+"毫秒");
	}
}

Operation result:

Time spent traversing the collection using iterators: 6 milliseconds
Time spent traversing the collection using the get method: 2509 milliseconds


Note: Java also provides a dynamic array table class ArrayList with a sequential structure, and the array table uses a sequential structure to store data . An array table is not suitable for dynamically changing the data it stores, such as adding and deleting cells, etc. (slower than a linked list). However, since the array table stores data in a sequential structure , the array table obtains the data in the nth unit faster than the linked list obtains the data in the nth unit. Many methods of the ArrayList class are similar to LinkedList. The essential difference between the two is that one uses a sequential structure and the other uses a chained structure.

A linked list object can be created with a normal LinkedList

LinkedList mylist = new LinkedList();

Then, the mylist linked list can use the add(Object obj) method to add nodes to this linked list in turn . Since any class is a subclass of the Object class, any object can be used as an object in the linked list node. It should be noted that when using get() to obtain an object in a node , the type conversion operator must be used to convert back to the original type. The main purpose of Java generics is to establish a type-safe collection framework . The advantage is that when using the data structures established by these generic classes , there is no need to perform mandatory type conversion, that is, no runtime type checking is required .

import java.util.Iterator;
import java.util.LinkedList;

public class Example13_4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LinkedList mylist = new LinkedList();
		mylist.add("你"); //链表中的第一个结点
		mylist.add("好"); //链表中的第二个结点
		int number = mylist.size(); //获取链表的长度
		for(int i=0;i<number;i++) {
			String temp = (String)mylist.get(i); //必须强制转换取出的数据
			System.out.println("第"+i+"结点中的数据:"+temp);
		}
		Iterator iter = mylist.iterator();
		while(iter.hasNext()) {
			String te = (String)iter.next();
			System.out.println(te);
		}
	}

}

 operation result:

 Data in node 0:
 data in your node 1: ok  hello
 


Use object flow to realize the entry and display system of commodity inventory . There is a "commodity" class that implements the interface Serializable . The program uses the object of this class as a link node, and then writes the linked list into a file.


public class Example13_5 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		WindowGoods win = new WindowGoods();
		win.setTitle("商品的录入与显示");
	}

}

Goods.java


public class Goods implements java.io.Serializable {
	String name, mount, price;

	public void setName(String name) {
		this.name = name;
	}

	public void setMount(String mount) {
		this.mount = mount;
	}

	public void setPrice(String price) {
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public String getMount() {
		return mount;
	}

	public String getPrice() {
		return price;
	}
}

InputArea.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;

import javax.swing.*;

public class InputArea extends JPanel implements ActionListener {
	File f = null; // 存放链表的文件
	Box baseBox, boxV1, boxV2;
	JTextField name, mount, price; // 为Goods对象提供的视图

	JButton button; // 控制器
	LinkedList<Goods> goodsList; // 存放Goods对象的链表

	InputArea(File f) {
		this.f = f;
		goodsList = new LinkedList<Goods>();
		name = new JTextField(12);
		mount = new JTextField(12);
		price = new JTextField(12);
		button = new JButton("录入");

		button.addActionListener(this);

		boxV1 = Box.createVerticalBox();

		boxV1.add(new JLabel("输入名称"));
		boxV1.add(Box.createVerticalStrut(8));
		boxV1.add(new JLabel("输入库存"));
		boxV1.add(Box.createVerticalStrut(8));
		boxV1.add(new JLabel("输入单价"));
		boxV1.add(Box.createVerticalStrut(8));
		boxV1.add(new JLabel("单击录入"));

		boxV2 = Box.createVerticalBox();
		boxV2.add(name);
		boxV2.add(Box.createVerticalStrut(8));
		boxV2.add(mount);
		boxV2.add(Box.createVerticalStrut(8));
		boxV2.add(price);
		boxV2.add(Box.createVerticalStrut(8));
		boxV2.add(button);

		baseBox = Box.createHorizontalBox();

		baseBox.add(boxV1);
		baseBox.add(Box.createHorizontalStrut(10));
		baseBox.add(boxV2);
		add(baseBox);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if (f.exists()) {
			try {
				FileInputStream fi = new FileInputStream(f);
				ObjectInputStream oi = new ObjectInputStream(fi);
				goodsList = (LinkedList<Goods>) oi.readObject();
				fi.close();
				oi.close();
				Goods goods = new Goods();
				goods.setName(name.getText());
				goods.setMount(mount.getText());
				goods.setPrice(price.getText());
				goodsList.add(goods);

				FileOutputStream fo = new FileOutputStream(f);
				ObjectOutputStream out = new ObjectOutputStream(fo);
				out.writeObject(goodsList);
				out.close();

			} catch (Exception ee) {
			}
		} else {
			try {
				f.createNewFile();
				Goods goods = new Goods();
				goods.setName(name.getText());
				goods.setMount(mount.getText());
				goods.setPrice(price.getText());
				goodsList.add(goods);
				FileOutputStream fo = new FileOutputStream(f);
				ObjectOutputStream out = new ObjectOutputStream(fo);
				out.writeObject(goodsList);
				out.close();
			} catch (Exception ee) {
			}
		}
	}
}

ShowArea.java

import java.awt.BorderLayout;
import java.awt.Event;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.JPanel;
import javax.swing.JTable;

public class ShowArea extends JPanel {
	JTable table;
	Object tableElement[][], name[] = { "名称", "库存", "单价" };

	public ShowArea() {
		setLayout(new BorderLayout());
		table = new JTable();
		add(table);
	}

	public void show(LinkedList<Goods> goodsList) {
		remove(table);
		int lenght = goodsList.size();
		tableElement = new Object[lenght][3];
		table = new JTable(tableElement, name);
		add(table);
		Iterator<Goods> iter = goodsList.iterator();
		int i = 0;
		while (iter.hasNext()) {
			Goods goods = iter.next();
			tableElement[i][0] = goods.getName();
			tableElement[i][1] = goods.getMount();
			tableElement[i][2] = goods.getPrice();
			i++;
		}
		table.repaint();
	}
}

WindowGoods.java

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.LinkedList;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class WindowGoods extends JFrame implements ActionListener {

	File file = null;
	JMenuBar bar;
	JMenu fileMenu;
	JMenuItem login, show;
	InputArea inputMessage; // 录入界面
	ShowArea showMessage; // 显示界面
	JPanel pCenter;
	CardLayout card;

	WindowGoods() {
		file = new File("库存.txt"); // 存放链表的文件
		login = new JMenuItem("录入");
		show = new JMenuItem("显示");
		bar = new JMenuBar();
		fileMenu = new JMenu("菜单选项");
		fileMenu.add(login);
		fileMenu.add(show);
		bar.add(fileMenu);
		setJMenuBar(bar);
		login.addActionListener(this);
		show.addActionListener(this);
		inputMessage = new InputArea(file); // 创建录入界面
		showMessage = new ShowArea(); // 创建显示界面
		card = new CardLayout();
		pCenter = new JPanel();
		pCenter.setLayout(card);
		pCenter.add("录入", inputMessage);
		pCenter.add("显示", showMessage);
		add(pCenter, BorderLayout.CENTER);
		card.show(pCenter, "录入");
		setVisible(true);
		setBounds(100, 50, 420, 380);
		validate();
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}

	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if (e.getSource() == login) {
			card.show(pCenter, "录入");
		} else if (e.getSource() == show) {
			try {
				FileInputStream fi = new FileInputStream(file);
				ObjectInputStream oi = new ObjectInputStream(fi);
				LinkedList<Goods> goodsList = (LinkedList<Goods>) oi.readObject();
				fi.close();
				oi.close();
				card.show(pCenter, "显示");
				showMessage.show(goodsList);

			} catch (Exception ee) {
				System.out.println(ee);
				JOptionPane.showMessageDialog(this, "没有信息", "提示对话框", JOptionPane.WARNING_MESSAGE);
			}
		}

	}

}

2. Stack

The heap is a "last in, first out" data structure, which can only input or output data at one end. The stack puts the first data put into the stack at the bottom, and puts the subsequent data on top of the existing data. The operation of inputting data into the stack is called "push", and the operation of outputting data from the stack is called " popping ". Since the stack always performs data input/output operations at the top, popping the stack always outputs (deletes) the data that was last pushed into the stack, which is the reason for "last in, first out".

Use the Stack<E> generic class in the java.util package to create a stack object , and the stack object can use " public E push(E item) ;" to implement the stack operation;  use " public E pop(); " to implement the pop-up stack Operation ; use " public boolean empty(); " to judge whether there is data in the stack, return false if there is data, otherwise return true; use " public E peek(); " to get the data at the top of the stack, but not delete the data; use " public int search(Object data); "Get the position of the data in the stack, the topmost position is 1, and increase downwards in turn, if the stack does not contain this data, return -1.
The stack is a very flexible data structure, and using the stack can save memory overhead .

For example, recursion is an algorithm that consumes a lot of memory, and most of the recursion can be eliminated by using the stack to achieve the same purpose as the recursive algorithm. The Fibonacci integer sequence is a recursive sequence that we are familiar with. Its nth item is the sum of the first two items, and the first and second items are 1. Example 13.6 below uses the stack to output the items of this recursive sequence .

import java.util.Stack;

public class Example13_6 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Stack<Integer>stack = new Stack<Integer>();
		stack.push(1);
		stack.push(1);
		int k = 1;
		while(k<=10) {
			for(int i=1;i<=2;i++) {
				int f1 = stack.pop();
				int f2 = stack.pop();
				int next = f1+f2;
				System.out.println(""+next);
				stack.push(next);
				stack.push(f2);
				k++;
			}
		}
	}

}

operation result:

2
3
5
8
13
21
34
55
89
144
 

Guess you like

Origin blog.csdn.net/m0_46965984/article/details/124212795
Recommended