Cấu trúc dữ liệu Java
- 20-12-2023
- Toanngo92
- 0 Comments
Khái niệm: Cấu trúc dữ liệu là cách tổ chức và lưu trữ dữ liệu để hiệu quả trong việc truy cập và sửa đổi. Việc sử dụng cấu trúc dữ liệu ảnh hưởng trực tiếp hiệu suất và hiệu quả của thuật toán.
Các Cấu trúc Dữ liệu Quan trọng:
- Mảng (Array)
- Danh sách Liên kết (LinkedList)
- Ngăn xếp (Stacks)
- Hàng đợi (Queues)
- Cây (Tree)
- Đồ thị (Graphs)
- Bảng Băm (Hash Tables)
Mục lục
Mảng tĩnh (Arrays)
Định nghĩa: Mảng là một tập hợp các phần tử được xác định bởi chỉ mục hoặc khóa.
Đặc tính: Kích thước cố định (nghĩa là bạn không thể dễ dàng thay đổi số lượng phần tử sau khi mảng đã được tạo).
Các loại Mảng:
- Mảng một chiều: Tương tự như danh sách đơn giản, ví dụ:
int[] array = new int[10];
. - Mảng đa chiều: Cấu trúc phức tạp hơn, ví dụ:
int[,] arr = new int[10][10];
.
Lợi ích:
- Truy cập nhanh qua chỉ mục.
- Cấu trúc đơn giản và triển khai dễ dàng.
Nhược điểm:
- Kích thước cố định hạn chế tính linh hoạt.
- Thao tác thay đổi kích thước có thể tốn kém.
Mảng Động (Dynamic Arrays)
Định nghĩa: Mảng động là mảng có thể tự điều chỉnh kích thước khi cần thêm không gian.
Cơ chế: Bắt đầu với kích thước cố định. Khi vượt quá dung lượng, tạo một mảng mới với kích thước gấp đôi và sao chép các phần tử.
Ưu điểm: Kích thước linh hoạt và tự động điều chỉnh kích thước.
Nhược điểm: Việc điều chỉnh kích thước có thể tốn kém.
Triển khai thông dụng: Trong Java, chúng ta sử dụng ArrayList là kiểu dữ liệu cho loại mảng này.
ArrayList<Integer> mangDong = new ArrayList<>();
mangDong.them(1);
mangDong.them(2);
System.out.println(mangDong.kichThuoc()); // Kết quả: 2
Danh sách liên kết
Định nghĩa: Danh sách liên kết là một cấu trúc dữ liệu tuyến tính, trong đó các phần tử được lưu trữ trong các nút, và mỗi nút chỉ đến nút tiếp theo.
Các loại danh sách liên kết:
- Danh sách liên kết đơn
- Danh sách liên kết kép
- Danh sách liên kết vòng
Tính chất của danh sách liên kết:
- Kích thước động (có thể thay đổi)
- Thao tác chèn/xóa hiệu quả
Ví dụ:
Tạo tệp Node.java
package linkedlistexam;
public class Node {
public int data;
public Node next;
public Node (int data){
this.data = data;
this.next = null;
}
}
Tạo tệp LinkedList.java
package linkedlistexam;
public class LinkedList {
private Node head;
public void insert(int data){
Node newNode = new Node(data);
if(head == null){
head = newNode;
} else {
Node temp = head;
while(temp.next != null){
temp = temp.next;
}
temp.next = newNode;
}
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
Node temp = head;
while(temp != null){
sb.append(temp.data).append(" ");
temp = temp.next;
}
return sb.toString();
}
}
Tạo tệp Main.java để test:
package linkedlistexam;
public class Main {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.insert(5);
list.insert(10);
list.insert(15);
list.insert(20);
System.out.println("Linked List:");
System.out.println(list);
}
}
Mảng so với LinkedList:
So sánh: Mảng có kích thước cố định, trong khi LinkedList có thể tăng động.
Truy cập hiệu quả so với Chèn/Xóa hiệu quả: Mảng cung cấp quyền truy cập hiệu quả (thời gian không đổi), nhưng LinkedList vượt trội về chèn và xóa (thời gian không đổi để thêm/xóa phần tử).
ArrayList so với LinkedList:
So sánh: ArrayList sử dụng mảng động bên trong, trong khi LinkedList dựa trên các nút (node).
Thời gian truy cập tốt hơn so với Chèn/Xóa tốt hơn: ArrayList cung cấp thời gian truy cập tốt hơn (do bộ nhớ liền kề), trong khi LinkedList hoạt động tốt hơn cho việc chèn và xóa (không cần dịch chuyển phần tử)
Giới thiệu về cấu trúc dữ liệu dạng cây (Tree)
Định nghĩa: Cấu trúc dữ liệu phân cấp bao gồm các nút được kết nối bởi các cạnh.
Tính chất:
- Một nút gốc ở cấp độ cao nhất.
- Một nút lá được kết nối bằng các cạnh từ các nút cha.
- Các nút con không có con.
Các loại cây:
- Cây nhị phân (Binary Tree): Mỗi nút có tối đa hai con.
- Cây nhị phân tìm kiếm: Cây phân tầng nhị phân với các node được sắp xếp (phần tử con trái < phần tử con phải).
- Cây tổng quát: Nút có thể có bất kỳ số lượng con nào.
Trường hợp sử dụng:
- Biểu diễn dữ liệu phân cấp (ví dụ: hệ thống tệp, biểu đồ tổ chức).
- Các ứng dụng tìm kiếm và sắp xếp (ví dụ: Cây tìm kiếm nhị phân).
Ví dụ cấu trúc dữ liệu dạng cây:
Ví dụ 1: Menu đa cấp (ví dụ: điều hướng website)
Cấp gốc: Trang chủ
Các mục con: Giới thiệu, Dịch vụ, Liên hệ
Các mục con tiếp theo dưới Dịch vụ: Phát triển web, Ứng dụng di động
Ví dụ 2: Mô hình Quận/Huyện
Cấp gốc: Quốc gia
Các mục con: Tỉnh/Thành phố
Các mục con tiếp theo dưới Tỉnh/Thành phố: Thành phố, Quận/Huyện
Ví dụ 3: Sơ đồ tổ chức
Cấp gốc: Giám đốc điều hành (CEO)
Các mục con: Trưởng các phòng ban (Nhân sự, Tài chính, Tiếp thị)
Các mục con tiếp theo dưới các phòng ban: Trưởng nhóm, Nhân viên
import java.util.ArrayList;
import java.util.List;
class TreeNode {
String data;
List<TreeNode> children;
TreeNode(String data) {
this.data = data;
this.children = new ArrayList<>();
}
void addChild(TreeNode child) {
children.add(child);
}
}
public class TreeExample {
public static void main(String[] args) {
// Sample tree creation:
TreeNode root = new TreeNode("CEO");
TreeNode hrHead = new TreeNode("HR Head");
root.addChild(hrHead);
TreeNode financeHead = new TreeNode("Finance Head");
root.addChild(financeHead);
}
}
Cấu trúc dữ liệu dạng bản đồ (Map)
Định nghĩa: Một tập hợp các cặp khóa-giá trị, trong đó mỗi khóa ánh xạ đến một giá trị cụ thể.
Các triển khai phổ biến:
- Hashtable: Bản đồ đồng bộ cho các cặp khóa-giá trị, không cho phép khóa hoặc giá trị null.
- HashMap: Phiên bản linh hoạt hơn, không đồng bộ, cho phép một khóa null và nhiều giá trị null.
Thuộc tính:
- Tìm kiếm và truy xuất theo khóa hiệu quả.
- Mỗi khóa là duy nhất, nhưng giá trị có thể trùng lặp.
Các trường hợp sử dụng:
- Tra cứu dữ liệu nhanh (ví dụ: lưu trữ thông tin người dùng theo ID).
- Lưu trữ cấu hình (ví dụ: thiết lập ứng dụng).
Ví dụ HashMap:
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
// Tạo một HashMap
HashMap<Integer, String> userMap = new HashMap<>();
// Thêm các cặp khóa-giá trị vào HashMap
userMap.put(1, "Alice");
userMap.put(2, "Bob");
userMap.put(3, "Charlie");
// Cho phép khóa hoặc giá trị null
userMap.put(null, "NullKeyUser");
userMap.put(4, null);
// Lấy và hiển thị các giá trị từ HashMap
System.out.println("User with ID 1: " + userMap.get(1));
System.out.println("User with null key: " + userMap.get(null));
// Duyệt qua các cặp khóa-giá trị
for (Integer key : userMap.keySet()) {
System.out.println("Key: " + key + ", Value: " + userMap.get(key));
}
}
}
Ví dụ Hashtable:
import java.util.Hashtable;
public class HashtableExample {
public static void main(String[] args) {
// Tạo một Hashtable
Hashtable<Integer, String> configMap = new Hashtable<>();
// Thêm các cặp khóa-giá trị vào Hashtable
configMap.put(1, "DatabaseURL");
configMap.put(2, "APIKey");
configMap.put(3, "Timeout");
// Không cho phép khóa hoặc giá trị null (sẽ gây ra lỗi nếu cố gắng sử dụng null)
// configMap.put(null, "NullKeyUser"); // Lỗi: NullPointerException
// configMap.put(4, null); // Lỗi: NullPointerException
// Lấy và hiển thị các giá trị từ Hashtable
System.out.println("Config 1: " + configMap.get(1));
System.out.println("Config 2: " + configMap.get(2));
// Duyệt qua các cặp khóa-giá trị
for (Integer key : configMap.keySet()) {
System.out.println("Key: " + key + ", Value: " + configMap.get(key));
}
}
}
So sánh giữa HashMap
và Hashtable
:
- HashMap:
- Cho phép một khóa
null
và nhiều giá trịnull
. - Không đồng bộ, nhanh hơn khi không yêu cầu sự an toàn luồng (thread safety).
- Cho phép một khóa
- Hashtable:
- Không cho phép khóa hoặc giá trị
null
. - Đồng bộ, an toàn cho các ứng dụng đa luồng nhưng có hiệu suất thấp hơn so với
HashMap
.
- Không cho phép khóa hoặc giá trị
Cấu trúc dữ liệu Stack (ngăn xếp)
Định nghĩa: Một cấu trúc dữ liệu tuyến tính tuân theo nguyên tắc Vào Sau, Ra Trước (LIFO – Last In, First Out).
Các thao tác:
- push: Thêm một phần tử vào đỉnh của ngăn xếp.
- pop: Xóa và trả về phần tử ở đỉnh ngăn xếp.
- peek: Xem phần tử ở đỉnh mà không xóa nó.
Trường hợp sử dụng:
- Hoàn tác các thao tác trong trình soạn thảo văn bản.
- Đánh giá các biểu thức số học.
- Đảo ngược dữ liệu (ví dụ: chuỗi).
Ví dụ:
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
// Tạo một Stack
Stack<String> stack = new Stack<>();
// Thêm các phần tử vào Stack (push)
stack.push("A");
stack.push("B");
stack.push("C");
// Xem phần tử trên cùng của Stack mà không xóa (peek)
System.out.println("Phần tử trên cùng: " + stack.peek());
// Loại bỏ và trả về phần tử trên cùng (pop)
System.out.println("Phần tử vừa loại bỏ: " + stack.pop());
// Hiển thị phần tử trên cùng sau khi pop
System.out.println("Phần tử trên cùng sau pop: " + stack.peek());
// Duyệt qua các phần tử trong Stack
System.out.println("Các phần tử còn lại trong stack:");
for (String element : stack) {
System.out.println(element);
}
}
}
Cấu trúc dữ liệu Queue (hàng đợi)
Định nghĩa: Một cấu trúc dữ liệu tuyến tính tuân theo nguyên tắc Vào Trước, Ra Trước (FIFO – First In, First Out).
Các thao tác:
- enqueue: Thêm một phần tử vào cuối hàng đợi.
- dequeue: Xóa và trả về phần tử ở đầu hàng đợi.
- peek: Xem phần tử ở đầu mà không xóa nó.
Trường hợp sử dụng:
- Hệ thống xử lý đơn hàng.
- Xử lý dữ liệu song song.
- Quản lý các tác vụ trong hàng đợi (ví dụ: công việc in ấn).
Ví dụ:
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
// Tạo một Queue
Queue<String> queue = new LinkedList<>();
// Thêm các phần tử vào Queue (enqueue)
queue.add("A");
queue.add("B");
queue.add("C");
// Xem phần tử ở đầu hàng đợi mà không xóa (peek)
System.out.println("Phần tử đầu tiên: " + queue.peek());
// Loại bỏ và trả về phần tử ở đầu hàng đợi (dequeue)
System.out.println("Phần tử vừa loại bỏ: " + queue.poll());
// Hiển thị phần tử ở đầu hàng đợi sau khi dequeue
System.out.println("Phần tử đầu tiên sau khi loại bỏ: " + queue.peek());
// Duyệt qua các phần tử còn lại trong Queue
System.out.println("Các phần tử còn lại trong queue:");
for (String element : queue) {
System.out.println(element);
}
}
}
Khái Niệm Máy Chủ Hàng Đợi (Queue Server)
Khái niệm: Một hệ thống xử lý các nhiệm vụ theo hàng đợi, thực hiện từng nhiệm vụ một.
Các Trường Hợp Sử Dụng Thông Dụng:
- Hàng Đợi Tin Nhắn (Messaging Queues): Được sử dụng trong các hệ thống như RabbitMQ, Apache Kafka để xử lý nhiệm vụ không đồng bộ.
- Máy Chủ In (Print Servers): Quản lý nhiều tác vụ in trong hàng đợi.
Ưu Điểm:
- Tách biệt các nhà sản xuất nhiệm vụ khỏi các người tiêu thụ nhiệm vụ, cải thiện khả năng mở rộng của hệ thống.
- Cho phép xử lý các nhiệm vụ theo thứ tự chúng đến.
Ví Dụ:
Hệ thống dịch vụ khách hàng nơi các yêu cầu được xử lý theo hàng đợi.
Giao diện Enumeration
Enumeration
là một giao diện trong gói java.util
định nghĩa các phương thức để lặp qua các phần tử của một tập hợp. Các phương thức của giao diện Enumeration
như sau:
hasMoreElements()
: Kiểm tra xem enumeration có chứa thêm phần tử nào không.nextElement()
: Trả về phần tử tiếp theo, nếu có, trong enumeration.
Ngoại lệ liên quan đến giao diện này là NoSuchElementException
. Ngoại lệ này sẽ được ném nếu nextElement()
được gọi khi không còn phần tử nào trong enumeration.
Đoạn mã dưới sử dụng một Enumeration
để lặp qua các phần tử của một mảng.
Ví dụ 1:
import java.lang.reflect.Array;
import java.util.Enumeration;
public class CustomEnumeration implements Enumeration {
private final int arraySize;
private int arrayCursor;
private final Object array;
public CustomEnumeration(Object obj) {
arraySize = Array.getLength(obj);
array = obj;
}
@Override
public boolean hasMoreElements() {
return (arrayCursor < arraySize);
}
@Override
public Object nextElement() {
return Array.get(array, arrayCursor++);
}
}
Đoạn mã tạo ra một lớp CustomEnumeration
triển khai giao diện Enumeration
. Constructor của lớp chấp nhận một đối tượng và lưu kích thước và đối tượng đó vào các biến arraySize
và array
tương ứng. Phương thức hasMoreElements()
được ghi đè để trả về true
nếu biến arrayCursor
nhỏ hơn arraySize
. Phương thức nextElement()
được ghi đè để trả về một đối tượng biểu diễn một phần tử trong mảng với chỉ số được xác định bởi biến arrayCursor
. Ví dụ dưới cho thấy class sử dụng custom enumeration được định nghĩa ở ví dụ 1.
Ví dụ 2:
import java.util.Enumeration;
public class EnumerationDemo {
public static void main(String[] args) {
String[] strArray = new String[]{"one", "Two", "Three"};
Enumeration customEnumeration = new CustomEnumeration(strArray);
while (customEnumeration.hasMoreElements()) {
System.out.println(customEnumeration.nextElement());
}
}
}
Phương thức main
trong đoạn mã tạo một thể hiện của CustomEnumeration
được khởi tạo với một mảng. Phương thức hasMoreElements()
trong vòng lặp while
kiểm tra xem có thêm phần tử nào trong mảng không. Nếu phương thức hasMoreElements()
trả về true
, phương thức nextElement()
sẽ in ra phần tử của mảng.
Output:
one
Two
Three
Lớp BitSet
Trong máy tính, một bit là đơn vị dữ liệu nhỏ nhất. Ứng dụng Java thường xuyên cần làm việc với lượng lớn bit và lớp BitSet
được thiết kế cho mục đích đó. Lớp BitSet
là một tập hợp các giá trị bit và có thể thay đổi kích thước theo yêu cầu. Một BitSet
lập chỉ mục cho các bit của nó bằng số nguyên không âm và mỗi bit trong BitSet
có thể được truy cập bằng chỉ mục của nó. Ưu điểm của BitSet
là nó chỉ sử dụng một bit để lưu trữ một giá trị.
Ví dụ:
import java.util.BitSet;
public class BitSetDemo {
public static void main(String[] args) {
BitSet bitSet1 = new BitSet();
BitSet bitSet2 = new BitSet();
bitSet1.set(1);
bitSet1.set(5);
bitSet1.set(8);
bitSet2.set(3);
bitSet2.set(6);
bitSet2.set(9);
System.out.println("Values in bitSet1: " + bitSet1);
System.out.println("Values in bitSet2: " + bitSet2);
}
}
Đoạn mã tạo ra hai đối tượng BitSet
và gọi phương thức set()
để khởi tạo chúng. Cuối cùng, các đối tượng BitSet
được in ra màn hình.
Output:
Values in bitSet1: {1, 5, 8}
Values in bitSet2: {3, 6, 9}
Lớp Stack
Một ngăn xếp là một tập hợp các đối tượng dựa trên nguyên tắc LIFO (Last-in First-out). Trong một ngăn xếp, phần tử cuối cùng được thêm vào, hoặc đẩy vào ngăn xếp là phần tử đầu tiên được loại bỏ, hoặc bật ra khỏi ngăn xếp. Lớp Stack
mở rộng từ lớp Vector
và ngoài các phương thức được kế thừa từ Vector
, Stack
định nghĩa năm phương thức, như liệt kê trong Bảng dưới:
Các Phương thức của Lớp Stack
Phương thức | Mô Tả |
---|---|
empty() | Kiểm tra xem Stack có trống không. |
peek() | Trả về đối tượng ở đỉnh của Stack mà không loại bỏ đối tượng. |
pop() | Trả về đối tượng ở đỉnh của Stack sau khi loại bỏ đối tượng từ Stack . |
push(E item) | Đẩy một đối tượng lên đỉnh của Stack . |
search(Object) | Trả về vị trí của một đối tượng từ đỉnh của Stack . Phương thức này trả về 1 cho đối tượng ở đỉnh ngăn xếp, 2 cho đối tượng bên dưới nó, và cứ như vậy. Nếu không tìm thấy đối tượng, phương thức này trả về -1. |
Ví dụ:
import java.util.Stack;
public class StackDemo {
private static Stack<String> getInitializedStack() {
Stack<String> stack = new Stack<>();
stack.push("obj1");
stack.push("obj2");
stack.push("obj3");
stack.push("obj4");
return stack;
}
public static void main(String[] args) {
Stack<String> initializedStack = StackDemo.getInitializedStack();
System.out.println("Object at top: " + initializedStack.peek());
System.out.println("Position of obj2 from top: " + initializedStack.search("obj2"));
System.out.println("Object popped out: " + initializedStack.pop());
System.out.println("Object at top: " + initializedStack.peek());
System.out.println("Elements in Stack---");
for (String obj : initializedStack) {
System.out.println(obj);
}
}
}
Phương thức getInitializedStack()
của đoạn mã tạo một Stack
và đẩy bốn đối tượng vào nó. Phương thức main()
gọi phương thức peek()
để lấy và in ra đối tượng ở đỉnh của Stack
.
Phương thức search()
lấy và in ra vị trí của đối tượng “obj2” từ đỉnh. Phương thức pop()
đẩy ra phần tử ở đỉnh và phương thức peek()
lấy và in ra phần tử hiện tại ở đỉnh. Cuối cùng, vòng lặp for cải tiến in ra từng phần tử hiện có trong Stack
.
Output:
Object at top: obj4
Position of obj2 from top: 3
Object popped out: obj4
Object at top: obj3
Elements in Stack---
obj3
obj2
obj1
Lớp Từ Điển (Dictionary)
Trong Java collections, một từ điển được sử dụng để lưu trữ các cặp khóa-giá trị. Mỗi khóa và giá trị trong một từ điển là một đối tượng. Lớp Dictionary
trong gói java.util
là lớp trừu tượng cha của tất cả các lớp thực hiện từ điển. Một số ví dụ về các lớp thực hiện từ điển là Hashtable
và Properties
.
Lớp Hashtable
Lớp Hashtable
thực hiện một tập hợp các cặp khóa-giá trị được tổ chức dựa trên mã băm của khóa. Mã băm là một số có dấu xác định khóa. Dựa trên mã băm, khi một cặp khóa-giá trị được thêm vào Hashtable
, nó được lưu trữ vào một bucket cụ thể. Hashtable
có tốc độ đáng kể nhanh so với các từ điển khác. Khi tìm kiếm được thực hiện cho một khóa, Hashtable
chỉ tìm kiếm trong một bucket cụ thể. Do đó, số lượng so sánh khóa giảm đáng kể.
Khi các phần tử được thêm vào Hashtable
, Hashtable
tự động thay đổi kích thước của mình bằng cách tăng dung lượng. Khi dung lượng của Hashtable
đạt đến dung lượng bạn chỉ định trong quá trình tạo, số lượng bucket tăng tự động. Nội tại, số lượng bucket được tăng lên thành số nguyên tố nhỏ nhất, lớn hơn gấp đôi số lượng hiện tại của các bucket trong lớp Hashtable
. Ví dụ, nếu số lượng hiện tại của bucket là 5 và Hashtable
đạt đến dung lượng ban đầu của nó, số lượng bucket sẽ tự động tăng lên thành 11.
Ví dụ:
import java.util.Enumeration;
import java.util.Hashtable;
public class HashtableDemo {
private static Hashtable<String, String> initializeHashtable() {
Hashtable<String, String> hTable = new Hashtable<>();
hTable.put("1", "East");
hTable.put("2", "West");
hTable.put("3", "North");
hTable.put("4", "South");
return hTable;
}
public static void main(String[] args) {
Hashtable<String, String> initializedTable = HashtableDemo.initializeHashtable();
Enumeration<String> e = initializedTable.keys();
System.out.println("---Hashtable Key-Value Pairs---");
while (e.hasMoreElements()) {
String key = e.nextElement();
System.out.println(key + " : " + initializedTable.get(key));
}
e = initializedTable.keys();
System.out.println("---Hashtable Keys---");
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
e = initializedTable.elements();
System.out.println("---Hashtable Values---");
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
}
}
Phương thức initializeHashtable()
của đoạn mã tạo một Hashtable
và đặt bốn cặp khóa-giá trị vào nó. Phương thức main()
sử dụng Enumeration
để lặp qua các khóa của Hashtable
và in ra các cặp khóa-giá trị, danh sách các khóa và danh sách giá trị của Hashtable
.
Output:
---Hashtable Key-Value Pairs---
1 : East
2 : West
3 : North
4 : South
---Hashtable Keys---
1
2
3
4
---Hashtable Values---
East
West
North
South
Lớp Properties
Lớp Properties
mở rộng từ Hashtable
để thực hiện một bộ sưu tập các cặp khóa-giá trị, trong đó cả hai loại khóa và giá trị đều là chuỗi. Mặc dù là một lớp con của Hashtable
, lớp Properties
kế thừa phương thức put()
để thêm một cặp khóa-giá trị, nhưng bạn nên tránh sử dụng nó. Điều này là do, nếu bạn thêm một khóa hoặc giá trị không phải là chuỗi, phương thức này sẽ thất bại khi chạy. Thay vào đó, bạn nên sử dụng phương thức setProperty()
để thêm cặp khóa-giá trị và phương thức getProperty()
để truy xuất một cặp khóa-giá trị.
Ví dụ:
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
private static Properties initializeProperties() {
Properties properties = new Properties();
properties.setProperty("1", "East");
properties.setProperty("2", "West");
properties.setProperty("3", "North");
properties.setProperty("4", "South");
return properties;
}
public static void main(String[] args) {
Properties initializedProperties = PropertiesDemo.initializeProperties();
Set<Object> set = initializedProperties.keySet();
Iterator<Object> itr = set.iterator();
while (itr.hasNext()) {
String key = (String) itr.next();
System.out.println("The value of " + key + " is " + initializedProperties.getProperty(key));
}
}
}
Phương thức initializeProperties()
của đoạn mã tạo một đối tượng Properties
và khởi tạo nó với các cặp khóa-giá trị thông qua các lời gọi đến phương thức setProperty()
. Phương thức main()
gọi phương thức keySet()
để trả về một đối tượng Set
chứa một tập hợp các khóa. Phương thức iterator()
trả về một đối tượng Iterator
được sử dụng để lặp qua các cặp khóa-giá trị. Đối với mỗi lần lặp, các cặp khóa-giá trị được in ra thông qua Iterator.next()
và Properties.getProperty()
.
Output:
The value of 1 is East
The value of 2 is West
The value of 3 is North
The value of 4 is South
Bài tập
- Task 1: Write a function to convert a list of arrays (e.g., categories and subcategories) into a tree structure.
- Task 2: Implement a function to traverse the tree and print it
- Task 3: Implement a simple contact list where names (keys) are stored with phone numbers (values) in a HashMap.
- Task 4: Write functions to add, remove, and search for contacts by name.
- Task 5: Extend the implementation to allow duplicate phone numbers with different names.
- Bonus Task: Sort the HashMap entries by key (name) and display the sorted contacts list
Bài tập queue/stack:
Task 1: Reversing a String with Stack
Description:
Write a function that uses a stack to reverse a given string.
- Sample Input: "hello"
- Expected Output: "olleh"
Task 2: Implementing a Queue for Task Management
Description:
- Implement a queue to simulate a task management system where tasks arrive and are processed in FIFO order.
- Write functions to enqueue new tasks, dequeue and process tasks, and view the current task at the front.
Task 3 (Optional): Queue for Parallel Data Processing
Description:
- Simulate a server that receives and processes requests in a queue. Implement multithreading to handle multiple tasks in parallel.
- Bonus: Introduce task priorities (PriorityQueue) to handle high-priority tasks first.