tek4

Lớp TreeSet trong Java

by - September. 26, 2021
Kiến thức
Học
Công nghệ
<p>Trong b&agrave;i viết n&agrave;y, ch&uacute;ng ta sẽ c&ugrave;ng t&igrave;m hiểu về lớp TreeSet trong Java v&agrave; c&aacute;c hoạt động v&agrave; phương thức kh&aacute;c nhau của n&oacute; c&ugrave;ng với sự trợ gi&uacute;p của c&aacute;c v&iacute; dụ dẫn chứng.</p> <h1>Lớp TreeSet</h1> <p>Lớp TreeSet trong Java cung cấp chức năng của cấu tr&uacute;c dữ liệu dạng c&acirc;y. N&oacute; triển khai cho NavigableSet Interface.</p> <p><img class="aligncenter wp-image-7739 size-full" style="display: block; margin-left: auto; margin-right: auto;" src="https://tek4.vn/wp-content/uploads/2021/01/Capture-117.png" alt="Lớp TreeSet trong Java" width="239" height="527" /></p> <h2>Tạo TreeSet</h2> <p>Để tạo một TreeSet, trước ti&ecirc;n ch&uacute;ng ta phải th&ecirc;m g&oacute;i java.util.TreeSet. V&agrave; sau đ&acirc;y l&agrave; c&aacute;ch ch&uacute;ng ta c&oacute; thể tạo một TreeSet trong Java.</p> <pre class="language-java"><code>TreeSet&lt;Integer&gt; a = new TreeSet&lt;&gt;();</code></pre> <p>Ở đ&acirc;y, ch&uacute;ng ta đ&atilde; tạo một TreeSet m&agrave; kh&ocirc;ng c&oacute; bất kỳ đối số n&agrave;o. Trong trường hợp n&agrave;y, c&aacute;c phần tử trong TreeSet được sắp xếp theo tự nhi&ecirc;n (thứ tự tăng dần). Tuy nhi&ecirc;n, ch&uacute;ng ta c&oacute; thể t&ugrave;y chỉnh việc sắp xếp c&aacute;c phần tử bằng c&aacute;ch sử dụng Comparator Interface. Ch&uacute;ng ta sẽ t&igrave;m hiểu về n&oacute; ở phần sau trong b&agrave;i viết n&agrave;y.</p> <h2>C&aacute;c phương thức của TreeSet</h2> <h3>1. Ch&egrave;n c&aacute;c phần tử</h3> <ul> <li>Phương thức add(): Ch&egrave;n phần tử được chỉ định v&agrave;o tập hợp.</li> <li>Phương thức addAll(): Ch&egrave;n tất cả c&aacute;c phần tử của tập hợp được chỉ định v&agrave;o tập hợp.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); System.out.println(sinh_vien); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.addAll(sinh_vien); System.out.println(sinh_vien2); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[Sinh vien Duoc, Sinh vien Luat, Sinh vien Y] [Sinh vien Duoc, Sinh vien Kinh te, Sinh vien Luat, Sinh vien Y]</code></pre> <h3>2. Truy cập c&aacute;c phần tử</h3> <p>Để truy cập c&aacute;c phần tử của một TreeSet, ch&uacute;ng ta c&oacute; thể sử dụng phương thức iterator(). Để sử dụng phương ph&aacute;p n&agrave;y, ch&uacute;ng ta cần phải th&ecirc;m g&oacute;i java.util.Iterator.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); System.out.println(sinh_vien); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.addAll(sinh_vien); Iterator&lt;String&gt; phan_tu = sinh_vien2.iterator(); while(phan_tu.hasNext()) { System.out.print(phan_tu.next()); System.out.print("\n"); } } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[Sinh vien Duoc, Sinh vien Luat, Sinh vien Y] Sinh vien Duoc Sinh vien Kinh te Sinh vien Luat Sinh vien Y</code></pre> <h3>3. X&oacute;a c&aacute;c phần tử</h3> <ul> <li>Phương thức remove(): X&oacute;a phần tử được chỉ định khỏi tập hợp.</li> <li>Phương thức removeAll(): X&oacute;a tất cả c&aacute;c phần tử khỏi tập hợp.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.addAll(sinh_vien); boolean kq = sinh_vien2.remove("Sinh vien Kinh te"); System.out.println(kq); System.out.println(sinh_vien2); boolean kq2 = sinh_vien2.removeAll(sinh_vien2); System.out.println(kq2); System.out.println(sinh_vien2); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>true [Sinh vien Duoc, Sinh vien Luat, Sinh vien Y] true []</code></pre> <h2>C&aacute;c phương thức điều hướng</h2> <p>V&igrave; lớp TreeSet thực hiện triển khai NavigableSet, n&oacute; cung cấp nhiều phương thức kh&aacute;c nhau để điều hướng qua c&aacute;c phần tử của TreeSet.</p> <h3>1. Phương thức first() v&agrave; last()</h3> <ul> <li>Phương thức first(): Trả về phần tử đầu ti&ecirc;n của tập hợp.</li> <li>Phương thức last(): Trả về phần tử cuối c&ugrave;ng của tập hợp.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.addAll(sinh_vien); String a = sinh_vien2.first(); System.out.println(a); String b = sinh_vien2.last(); System.out.println(b); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>Sinh vien Duoc Sinh vien Y</code></pre> <h3>2. C&aacute;c phương thức ceiling(), floor(), higher() v&agrave; lower()</h3> <ul> <li>Phương thức higher(phần tử): Trả về phần tử thấp nhất trong số c&aacute;c phần tử lớn hơn phần tử được chỉ định.</li> <li>Phương thức lower(phần tử): Trả về phần tử lớn nhất trong số c&aacute;c phần tử nhỏ hơn phần tử được chỉ định.</li> <li>Phương thức ceiling(phần tử): Trả về phần tử thấp nhất trong số c&aacute;c phần tử lớn hơn phần tử đ&atilde; chỉ định. Nếu phần tử tồn tại trong một TreeSet, n&oacute; sẽ trả về phần tử được truyền dưới dạng đối số.</li> <li>Phương thức floor(phần tử): Trả về phần tử lớn nhất trong số c&aacute;c phần tử nhỏ hơn phần tử đ&atilde; chỉ định. Nếu phần tử được truyền tồn tại trong một TreeSet, n&oacute; sẽ trả về phần tử được truyền dưới dạng đối số.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;Integer&gt; so_nguyen = new TreeSet&lt;&gt;(); so_nguyen.add(45); so_nguyen.add(43); so_nguyen.add(22); so_nguyen.add(78); System.out.println(so_nguyen.higher(43)); System.out.println(so_nguyen.lower(45)); System.out.println(so_nguyen.ceiling(78)); System.out.println(so_nguyen.floor(22)); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>45 43 78 22</code></pre> <h3>3. Phương thức pollfirst() v&agrave; pollLast()</h3> <ul> <li>Phương thức pollFirst(): Trả về v&agrave; x&oacute;a phần tử đầu ti&ecirc;n khỏi tập hợp.</li> <li>Phương thức pollLast(): Trả về v&agrave; x&oacute;a phần tử cuối c&ugrave;ng khỏi tập hợp.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;Integer&gt; so_nguyen = new TreeSet&lt;&gt;(); so_nguyen.add(45); so_nguyen.add(43); so_nguyen.add(22); so_nguyen.add(78); System.out.println(so_nguyen.pollFirst()); System.out.println(so_nguyen.pollLast()); System.out.println(so_nguyen); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>22 78 [43, 45]</code></pre> <h3>4. Phương thức headSet (), tailSet () v&agrave; subSet ()</h3> <p><strong>Phương thức headSet (phần tử, gi&aacute; trị kiểu boolean)</strong></p> <ul> <li>Phương thức headSet() trả về tất cả c&aacute;c phần tử của một TreeSet trước phần tử được chỉ định (được truyền dưới dạng đối số).</li> <li>Tham số thứ 2 l&agrave; t&ugrave;y chọn. Gi&aacute; trị mặc định của n&oacute; l&agrave; false. Nếu true được truyền cho tham số n&agrave;y, phương thức trả về tất cả c&aacute;c phần tử trước phần tử được chỉ định, bao gồm cả phần tử được chỉ định.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;Integer&gt; so_nguyen = new TreeSet&lt;&gt;(); so_nguyen.add(45); so_nguyen.add(43); so_nguyen.add(22); so_nguyen.add(78); System.out.println(so_nguyen.headSet(30, true)); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[22]</code></pre> <p><strong>Phương thức tailSet (phần tử, gi&aacute; trị kiểu boolean)</strong></p> <ul> <li>Phương thức tailSet() trả về tất cả c&aacute;c phần tử của một TreeSet sau phần tử được chỉ định (được truyền dưới dạng tham số) bao gồm cả phần tử được chỉ định.</li> <li>Tham số thứ 2 l&agrave; t&ugrave;y chọn. Gi&aacute; trị mặc định của n&oacute; l&agrave; true. Nếu false được truyền cho tham số n&agrave;y, phương thức trả về tất cả c&aacute;c phần tử sau phần tử được chỉ định m&agrave; kh&ocirc;ng bao gồm phần tử đ&atilde; chỉ định.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;Integer&gt; so_nguyen = new TreeSet&lt;&gt;(); so_nguyen.add(45); so_nguyen.add(43); so_nguyen.add(22); so_nguyen.add(78); System.out.println(so_nguyen.tailSet(30, false)); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[43, 45, 78]</code></pre> <p><strong>Phương thức subSet(e1, bv1, e2, bv2)</strong></p> <ul> <li>Phương thức subSet() trả về tất cả c&aacute;c phần tử giữa e1 v&agrave; e2 kể cả e1.</li> <li>bv1 v&agrave; bv2 l&agrave; c&aacute;c tham số t&ugrave;y chọn. Gi&aacute; trị mặc định của bv1 l&agrave; true v&agrave; gi&aacute; trị mặc định của bv2 l&agrave; false.</li> <li>Nếu false được truyền bv1, phương thức trả về tất cả c&aacute;c phần tử giữa e1 v&agrave; e2 m&agrave; kh&ocirc;ng bao gồm e1.</li> <li>Nếu true được truyền cho bv2, phương thức trả về tất cả c&aacute;c phần tử giữa e1 v&agrave; e2, bao gồm cả e1.</li> </ul> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;Integer&gt; so_nguyen = new TreeSet&lt;&gt;(); so_nguyen.add(45); so_nguyen.add(43); so_nguyen.add(22); so_nguyen.add(78); System.out.println(so_nguyen.subSet(30, false, 80, true)); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[43, 45, 78]</code></pre> <h2>C&aacute;c thao t&aacute;c với tập hợp</h2> <h3>1. Kết hợp c&aacute;c tập hợp</h3> <p>Để thực hiện kết hợp giữa hai tập hợp, ch&uacute;ng ta sử dụng phương thức addAll().</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.addAll(sinh_vien); System.out.println(sinh_vien2); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[Sinh vien Duoc, Sinh vien Kinh te, Sinh vien Luat, Sinh vien Y]</code></pre> <h3>2. T&igrave;m tập giao của c&aacute;c tập hợp</h3> <p>Để thực hiện phần giao nhau giữa hai tập hợp, ch&uacute;ng ta sử dụng phương thức retainAll().</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.retainAll(sinh_vien); System.out.println(sinh_vien2); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[]</code></pre> <h3>3. T&igrave;m sự kh&aacute;c nhau giữa hai tập hợp</h3> <p>Để t&iacute;nh to&aacute;n sự kh&aacute;c biệt giữa hai tập hợp, ch&uacute;ng ta c&oacute; thể sử dụng phương thức removeAll().</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Iterator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.add("Sinh vien Duoc"); sinh_vien2.removeAll(sinh_vien); System.out.println(sinh_vien2); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[Sinh vien Kinh te]</code></pre> <h3>4. Kiểm tra tập con của một tập hợp</h3> <p>Để kiểm tra xem một tập hợp c&oacute; phải l&agrave; tập hợp con của tập hợp kh&aacute;c hay kh&ocirc;ng, ch&uacute;ng ta sử dụng phương thức containsAll().</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); TreeSet&lt;String&gt; sinh_vien2 = new TreeSet&lt;&gt;(); sinh_vien2.add("Sinh vien Kinh te"); sinh_vien2.add("Sinh vien Duoc"); sinh_vien2.removeAll(sinh_vien); boolean kq = sinh_vien.containsAll(sinh_vien2); System.out.println(kq); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>False</code></pre> <h2>C&aacute;c phương thức kh&aacute;c</h2> <table width="787"> <tbody> <tr> <td style="text-align: center;">Phương thức</td> <td style="text-align: center;">M&ocirc; tả</td> </tr> <tr> <td>clone()</td> <td>Tạo một bản sao ch&eacute;p của TreeSet.</td> </tr> <tr> <td>contains()</td> <td>Trả về kết quả c&oacute; kiểu Boolean nếu tồn tại phần tử trong TreeSet.</td> </tr> <tr> <td>isEmpty()</td> <td>Kiểm tra TreeSet rỗng hay kh&ocirc;ng.</td> </tr> <tr> <td>size()</td> <td>Trả về k&iacute;ch thước của TreeSet.</td> </tr> <tr> <td>clear()</td> <td>X&oacute;a tất cả c&aacute;c phần tử khỏi TreeSet.</td> </tr> </tbody> </table> <h2>So s&aacute;nh lớp HashSet v&agrave; lớp TreeSet trong Java</h2> <p>Cả TreeSet cũng như HashSet đều triển khai cho Set Interface. Tuy nhi&ecirc;n, tồn tại một số kh&aacute;c biệt sau:</p> <ul> <li>Kh&ocirc;ng giống như HashSet, c&aacute;c phần tử trong TreeSet được lưu trữ theo một số thứ tự. Đ&oacute; l&agrave; v&igrave; TreeSet triển khai cho SortedSet Interface.</li> <li>TreeSet cung cấp một số phương ph&aacute;p để điều hướng dễ d&agrave;ng. V&iacute; dụ, first(), last(), headSet(), tailSet() bởi TreeSet cũng thực hiện triển khai cho NavigableSet Interface.</li> <li>HashSet nhanh hơn TreeSet trong c&aacute;c thao t&aacute;c cơ bản như th&ecirc;m, bớt, chứa v&agrave; k&iacute;ch thước.</li> </ul> <h2>Comparator trong TreeSet</h2> <p>Trong tất cả c&aacute;c v&iacute; dụ tr&ecirc;n, c&aacute;c phần tử của TreeSet được sắp xếp tự nhi&ecirc;n. Tuy nhi&ecirc;n, ch&uacute;ng ta cũng c&oacute; thể t&ugrave;y chỉnh thứ tự của c&aacute;c phần tử.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.util.TreeSet; import java.util.Comparator; class Main { public static void main(String[] args) { TreeSet&lt;String&gt; sinh_vien = new TreeSet&lt;&gt;(new CustomComparator()); sinh_vien.add("Sinh vien Kinh te"); sinh_vien.add("Sinh vien Y"); sinh_vien.add("Sinh vien Luat"); sinh_vien.add("Sinh vien Duoc"); System.out.println(sinh_vien); } public static class CustomComparator implements Comparator&lt;String&gt; { @Override public int compare(String a, String b) { int gia_tri = a.compareTo(b); if (gia_tri &gt; 0) { return -1; } else if (gia_tri &lt; 0) { return 1; } else { return 0; } } } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>[Sinh vien Y, Sinh vien Luat, Sinh vien Kinh te, Sinh vien Duoc]</code></pre> <p>Trong v&iacute; dụ tr&ecirc;n, ch&uacute;ng ta đ&atilde; tạo một TreeSet v&agrave; truyền lớp CustomComparator l&agrave;m đối số. Lớp CustomComparator triển khai cho Comparator Interface. Sau đ&oacute;, ch&uacute;ng ta ghi đ&egrave; phương thức compare(). Phương thức b&acirc;y giờ sẽ sắp xếp c&aacute;c phần tử theo thứ tự ngược lại.</p> <p>Tr&ecirc;n đ&acirc;y l&agrave; kh&aacute;i niệm v&agrave; v&iacute; dụ cơ bản về lớp TreeSet trong Java. Hy vọng mọi người c&oacute; thể &aacute;p dụng v&agrave;o trong chương tr&igrave;nh của m&igrave;nh. Mọi người h&atilde;y tiếp tục theo d&otilde;i c&aacute;c b&agrave;i tiếp theo v&agrave; cập nhật c&aacute;c b&agrave;i mới nhất tr&ecirc;n <a href="http://tek4.vn">tek4</a> nh&eacute;!</p>