Java LinkedHashSet类使用教程

x33g5p2x  于2021-08-21 转载在 Java  
字(5.9k)|赞(0)|评价(0)|浏览(503)

在本指南中,我们将通过实例学习Set接口的LinkedHashSet类的实现。

LinkedHashSet类是Set接口的Hash和LinkedList实现,具有可预测的迭代顺序。这个实现与HashSet的不同之处在于,它维护了一个贯穿其所有条目的双链表。这个链接列表定义了迭代顺序,也就是元素被插入集合的顺序(插入顺序)。
本指南涵盖了所有重要的LinkedHashSet类API,并附有示例。

我们将学到什么?

    1. LinkedHashSet类的概述
  1. 创建LinkedHashSet实例
  2. LinkedHashSet插入顺序示例
  3. LinkedHashSet用实例删除API。
  4. 遍历一个LinkedHashSet
  5. 带有用户定义对象的LinkedHashSet
  6. 如何使LinkedHashSet线程安全?

1. LinkedHashSet类的概述

  • Java LinkedHashSet类是Set接口的哈希表和关联列表的实现。
  • 像HashSet一样只包含唯一的元素。
  • 提供所有可选的集合操作,并允许空元素。
  • 保持插入的顺序。
  • LinkedHashSet是不同步的 - 如果多个线程同时访问一个链接哈希集,并且至少有一个线程修改了该集,那么它必须在外部进行同步。例子。
Set s = Collections.synchronizedSet(new LinkedHashSet(...));

2. 创建LinkedHashSet

// Creating a HashSet
LinkedHashSet<String> daysOfWeek = new LinkedHashSet<>();

// Adding new elements to the HashSet
daysOfWeek.add("Monday");
daysOfWeek.add("Tuesday");
daysOfWeek.add("Wednesday");
daysOfWeek.add("Thursday");
daysOfWeek.add("Friday");
daysOfWeek.add("Saturday");
daysOfWeek.add("Sunday");

// Adding duplicate elements will be ignored
daysOfWeek.add("Monday");

System.out.println(daysOfWeek);

输出。

[Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]

注意,它保持了插入顺序。

###3. LinkedHashSet插入顺序示例

package com.ramesh.corejava.devguide.classestypes.set;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class SetInterfaceLinkedHashSetImpl {
 public static void main(String[] args) {
  linkedHashSetDemo();
 }

 private static void linkedHashSetDemo() {
  Set<String> set = new LinkedHashSet<>();
  set.add("element 1");
  set.add("element 2");
  set.add("element 3");
  set.add("element 4");
  Iterator<String> iterator = set.iterator();
  while (iterator.hasNext()) {
   String str = iterator.next();
   System.out.println("LinkedHashSet does maintain " 
   + " insertion order ---" + str);
  }

  // loop using java 8
  set.forEach(str -> System.out.println("LinkedHashSet does "
  + " maintain insertion order ---" + str));
 }
}

输出:

LinkedHashSet does maintain  insertion order ---element 1
LinkedHashSet does maintain  insertion order ---element 2
LinkedHashSet does maintain  insertion order ---element 3
LinkedHashSet does maintain  insertion order ---element 4
LinkedHashSet does  maintain insertion order ---element 1
LinkedHashSet does  maintain insertion order ---element 2
LinkedHashSet does  maintain insertion order ---element 3
LinkedHashSet does  maintain insertion order ---element 4

4. LinkedHashSet删除API的例子

remove(Object o)

LinkedHashSet中删除一个元素(如果该元素不存在于LinkedHashSet 中,remove()方法返回false)

Set<Integer> numbers = new LinkedHashSet<>();
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
numbers.add(6);
numbers.add(7);
numbers.add(8);
numbers.add(9);
numbers.add(10);

System.out.println("numbers : " + numbers);

boolean isRemoved = numbers.remove(10);
System.out.println("After remove(10) => " + numbers);

removeAll(Collection<?> c)

LinkedHashSet中删除属于某个集合的所有元素。

Set<Integer> numbers = new LinkedHashSet<>();
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
numbers.add(6);
numbers.add(7);
numbers.add(8);
numbers.add(9);
numbers.add(10);
List<Integer> perfectSquares = new ArrayList<>();
perfectSquares.add(4);
perfectSquares.add(9);

numbers.removeAll(perfectSquares);
System.out.println("After removeAll(perfectSquares) => " + numbers);

removeIf(Predicate<? super Integer> filter)

删除所有与给定谓词匹配的元素

numbers.removeIf(num -> num % 2 == 0);
System.out.println("After removeIf() => " + numbers);

clear()

删除LinkedHashSet中的所有元素(完全清除)

numbers.clear();
System.out.println("After clear() => " + numbers);

5. 遍历一个LinkedHashSet

下面的例子显示了对HashSet进行迭代的不同方法

  • 使用Java 8 forEach和lambda表达式对LinkedHashSet进行迭代。
  • 使用iterator().LinkedHashSet进行遍历。
  • 使用iterator()和Java 8 forEachRemaining()方法对LinkedHashSet进行遍历。
  • 使用一个简单的for-each循环对LinkedHashSet进行迭代。

iterator()

Set<String> list = new LinkedHashSet<>();
list.add("element 1");
list.add("element 2");
list.add("element 3");
list.add("element 4");

// using Iterator
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
 String str = iterator.next();
 System.out.println(" only forward direction ---" + str);
}

推进for()循环

// Using advanced for loop
for (String str : list) {
 System.out.println(" only forward direction ---" + str);
}

forEachRemaining()

// Java 8
list.forEachRemaining(str -> System.out.println(" only forward direction ---" + str));

forEach()

// Java 8
list.forEach(str -> System.out.println(" only forward direction ---" + str));

6. LinkedHashSet与用户定义的对象

这个例子显示了如何创建一个LinkedHashSet的用户定义对象,并且它保持了插入的顺序。

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Customer {
    private long id;
    private String name;

    public Customer(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    // Two customers are equal if their IDs are equal
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer customer = (Customer) o;
        return id == customer.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

public class HashSetUserDefinedObjectExample {
    public static void main(String[] args) {
        Set<Customer> customers = new LinkedHashSet<>();
        customers.add(new Customer(101, "Rajeev"));
        customers.add(new Customer(102, "Sachin"));
        customers.add(new Customer(103, "Chris"));

        //*
HashSet will use the `equals()` & `hashCode()` implementations 
of the Customer class to check for duplicates and ignore them
/*/
        customers.add(new Customer(101, "Rajeev"));

        System.out.println(customers);
    }
}

7. 如何使LinkedHashSet线程安全?

这个类的实现是不同步的,所以它不是线程安全的。如果多个线程同时访问一个哈希集合,并且至少有一个线程修改了这个集合,那么必须在外部进行同步。LinkedHashSet必须是外部同步的。例子:

// HashSet is not synchronized
private static void synchronizedHashSetDemo() {
 Set<String> set = new LinkedHashSet<>();
 Set<String> synchronizedSet = Collections.synchronizedSet(set);
}

相关文章