java中hashset_Java HashSet – Java中的HashSet

java中hashset

Java HashSet is the most popular implementation of Set interface. java.util.HashSet is backed by a HashMap. HashSet extends AbstractSet class and implements Set, Cloneable and Serializable interfaces.

Java HashSet是Set接口的最流行实现。 HashMap支持java.util.HashSet。 HashSet扩展了AbstractSet类并实现Set,Cloneable和Serializable接口。

Java HashSet (Java HashSet)

Some of the important points about HashSet in java are;

Java中有关HashSet的一些重要要点是:

  1. HashSet doesn’t allow duplicate entries.

    HashSet不允许重复的条目。
  2. HashSet allows null as a value.

    HashSet允许将null作为值。
  3. HashSet doesn’t guarantee the insertion order of elements.

    HashSet不保证元素的插入顺序。
  4. HashSet is not thread-safe. You can get thread-safe HashSet using Collections.synchronizedSet method at the cost of performance. You can also use CopyOnWriteArraySet concurrency class for thread safety.

    HashSet不是线程安全的。 您可以使用Collections.synchronizedSet方法获取线程安全的HashSet,但会降低性能。 您也可以将CopyOnWriteArraySet并发类用于线程安全。
  5. HashSet iterator methods are fail-fast. So any structural modification to the set after creation of iterator will throw ConcurrentModificationException.

    HashSet迭代器方法快速失败。 因此,在创建迭代器之后对该集合进行的任何结构修改都将引发ConcurrentModificationException。
  6. HashSet supports Generics, this is the recommended approach to avoid ClassCastException at runtime.

    HashSet支持泛型,这是在运行时避免ClassCastException的推荐方法。
  7. HashSet uses HashMap for storing elements, so the objects should provide good implementation of hashCode() and equals() method to avoid unwanted results.

    HashSet使用HashMap来存储元素,因此对象应提供hashCode()和equals()方法的良好实现,以避免产生不必要的结果。

Java HashSet构造函数 (Java HashSet Constructors)

Java HashSet provides four constructors.

Java HashSet提供了四个构造函数。

  1. public HashSet(): Creates a new empty HashSet, the backing HashMap is initialized with default initial capacity as 16 and load factor 0.75.

    public HashSet() :创建一个新的空HashSet,使用默认的初始容量16和负载因子0.75初始化后备HashMap。
  2. public HashSet(int initialCapacity): Creates a empty HashSet with backing HashMap initialized with specified capacity and load factor 0.75.

    public HashSet(int initialCapacity) :创建一个空HashSet,并使用指定的容量和负载系数0.75初始化后备HashMap。
  3. public HashSet(int initialCapacity, float loadFactor): Creates a empty HashSet with backing HashMap initialized with specified capacity and specified load factor.

    public HashSet(int initialCapacity,float loadFactor) :创建一个空HashSet,并使用指定的容量和指定的加载因子初始化后备HashMap。
  4. public HashSet(Collection<? extends E> c): Creates a new Set containing the elements in the specified collection. The backing HashMap is created with default load factor (0.75) and an initial capacity sufficient enough to contain all the elements in the specified collection.

    public HashSet(Collection <?extends E> c) :创建一个包含指定集合中元素的新Set。 使用默认的加载因子(0.75)和足以容纳指定集合中所有元素的初始容量创建后备HashMap。

Below code snippet is showing all these HashSet constructors example usage.

下面的代码片段显示了所有这些HashSet构造函数示例用法。

Set<String> set = new HashSet<>();

//initial capacity should be power of 2
set = new HashSet<>(32); 

//setting backing HashMap initial capacity and load factor
set = new HashSet<>(32, 0.80f);

//creating HashSet from another Collection
Set<String> set1 = new HashSet<>(set);
Set<String> set2 = new HashSet<>(new ArrayList<>());

Java HashSet方法 (Java HashSet Methods)

Some of the useful HashSet methods are;

一些有用的HashSet方法是:

  1. public boolean add(E e): Adds the given element to the Set if not already present. This method internally uses equals() method to check for duplicates, so make sure your object defines equals() method properly.

    public boolean add(E e) :如果给定元素不存在,则将其添加到Set中。 此方法在内部使用equals()方法检查重复项,因此请确保您的对象正确定义了equals()方法。
  2. public void clear(): Removes all the elements from the Set.

    public void clear() :从集合中删除所有元素。
  3. public Object clone(): Returns a shallow copy of the Set instance.

    public Object clone() :返回Set实例的浅表副本。
  4. public boolean contains(Object o): Returns true if the Set contains the given element, othrweise false.

    public boolean contains(Object o) :如果Set包含给定元素,则返回true,否则返回false。
  5. public boolean isEmpty(): Returns true if Set contains no elements, otherwise false.

    public boolean isEmpty() :如果Set不包含任何元素,则返回true,否则返回false。
  6. public Iterator<E> iterator(): Returns an iterator over the elements in this set. The elements are returned in no particular order.

    public Iterator <E> iterator() :返回对此集合中的元素进行迭代的迭代器。 元素以不特定的顺序返回。
  7. public boolean remove(Object o): Removes the given element from this set if it is present and return true. If the element is not present in the set, just returns false.

    public boolean remove(Object o) :从该集合中删除给定的元素(如果存在)并返回true。 如果该元素不存在,则返回false。
  8. public int size(): Returns the number of elements in the set.

    public int size() :返回集合中元素的数量。
  9. public Spliterator<E> spliterator(): Creates a late-binding and fail-fast Spliterator over the elements in this set. This is introduced in Java 8, however I have not used it till now.

    public Spliterator <E> splitter() :在此集合中的元素上创建后绑定和故障快速的Spliterator。 这是Java 8中引入的,但是到目前为止我还没有使用过。
  10. public boolean removeAll(Collection<?> c): HashSet inherits this method from AbstractSet. This method will remove all the elements in the set that are part of the specified collection.

    public boolean removeAll(Collection <?> c) :HashSet从AbstractSet继承此方法。 此方法将删除集合中属于指定集合的​​所有元素。

Java HashSet示例 (Java HashSet Example)

Java HashSet example program showing common usage of HashSet in java.

Java HashSet示例程序,显示了Java中HashSet的常见用法。

package com.journaldev.examples;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class HashSetExample {

	public static void main(String[] args) {

		Set<String> fruits = new HashSet<>();
		
		//add example
		fruits.add("Apple");
		fruits.add("Banana");
		
		//isEmpty example
		System.out.println("fruits set is empty = "+fruits.isEmpty());

		//contains example
		System.out.println("fruits contains Apple = "+fruits.contains("Apple"));
		System.out.println("fruits contains Mango = "+fruits.contains("Mango"));
		
		//remove example
		System.out.println("Apple removed from fruits set = "+fruits.remove("Apple"));
		System.out.println("Mango removed from fruits set = "+fruits.remove("Mango"));
		
		//size example
		System.out.println("fruits set size = "+fruits.size());
		
		//addAll example
		List<String> list = new ArrayList<>(); 
		list.add("Apple"); list.add("Apple"); 
		list.add("Banana"); list.add("Mango");
		
		System.out.println("fruits set before addAll = "+fruits);
		System.out.println("list = "+list);
		fruits.addAll(list);
		System.out.println("fruits set after addAll = "+fruits);

		//iterator example
		Iterator<String> iterator = fruits.iterator();
		while(iterator.hasNext()){
			System.out.println("Consuming fruit "+iterator.next());
		}
		
		//removeAll example
		fruits.add("Orange");
		System.out.println("fruits set before removeAll = "+fruits);
		System.out.println("list = "+list);
		fruits.removeAll(list);
		System.out.println("fruits set after removeAll = "+fruits);
		
		//clear example
		fruits.clear();
		System.out.println("fruits set is empty = "+fruits.isEmpty());

	}

}

Output of above HashSet example program is given below, I am not explaining them since they are self understood.

上面的HashSet示例程序的输出如下所示,因为它们是我自己理解的,所以我不解释它们。

fruits set is empty = false
fruits contains Apple = true
fruits contains Mango = false
Apple removed from fruits set = true
Mango removed from fruits set = false
fruits set size = 1
fruits set before addAll = [Banana]
list = [Apple, Apple, Banana, Mango]
fruits set after addAll = [Apple, Mango, Banana]
Consuming fruit Apple
Consuming fruit Mango
Consuming fruit Banana
fruits set before removeAll = [Apple, Mango, Orange, Banana]
list = [Apple, Apple, Banana, Mango]
fruits set after removeAll = [Orange]
fruits set is empty = true

Java HashSet ConcurrentModificationException示例 (Java HashSet ConcurrentModificationException Example)

Java HashSet iterator is fail-fast, so it’s methods will throw java.util.ConcurrentModificationException if Set is structurally modified. Below is a simple example demonstrating this.

Java HashSet迭代器是快速失败的,因此,如果对Set进行结构上的修改,它的方法将抛出java.util.ConcurrentModificationException 。 下面是一个简单的示例来说明这一点。

package com.journaldev.examples;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetConcurrentModificationExceptionExample {

	public static void main(String[] args) {
		Set<String> fruits = new HashSet<>();
		
		//add example
		fruits.add("Apple");
		fruits.add("Banana");
		fruits.add("Orange");
		fruits.add("Mango");
		
		Iterator<String> iterator = fruits.iterator();
		
		while(iterator.hasNext()){
			String fruit = iterator.next();
			System.out.println("Processing "+fruit);
			
			//wrong way of removing from Set, can throw java.util.ConcurrentModificationException
			if("Orange".equals(fruit)) fruits.remove("Orange");
		}
	}

}

I am getting below output and exception when above program is executed.

执行上面的程序时,我得到下面的输出和异常。

Processing Apple
Processing Mango
Processing Orange
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
	at java.util.HashMap$KeyIterator.next(HashMap.java:1453)
	at com.journaldev.examples.HashSetConcurrentModificationExceptionExample.main(HashSetConcurrentModificationExceptionExample.java:21)

Note that HashSet elements are not guaranteed to be ordered and ConcurrentModificationException is being thrown by iterator.next() call. So if the “Orange” is the last one in the iterator, you will not get the exception because iterator.hasNext() will return false and iterator.next() will not get called.

请注意,不能保证HashSet元素是有序的,并且iterator.next()调用会引发ConcurrentModificationException 。 因此,如果“橙色”是迭代器中的最后一个,则不会收到异常,因为iterator.hasNext()将返回false,并且iterator.next()将不会被调用。

We should always use Iterator methods for structural modification, as shown in below example code.

我们应该始终使用Iterator方法进行结构修改,如下面的示例代码所示。

package com.journaldev.examples;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetConcurrentModificationExceptionExample {

	public static void main(String[] args) {
		Set<String> fruits = new HashSet<>();
		
		fruits.add("Apple");
		fruits.add("Banana");
		fruits.add("Orange");
		fruits.add("Mango");
		
		Iterator<String> iterator = fruits.iterator();
		
		while(iterator.hasNext()){
			String fruit = iterator.next();
			System.out.println("Processing "+fruit);
			
			//correct way of structural modification of Set
			if("Orange".equals(fruit)) iterator.remove();
		}
		System.out.println("fruits set after iteration = "+fruits);
	}

}

Above HashSet iterator example will not throw exception and you will get below output.

上面的HashSet迭代器示例不会引发异常,您将得到下面的输出。

Processing Apple
Processing Mango
Processing Orange
Processing Banana
fruits set after iteration = [Apple, Mango, Banana]

Java HashSet到数组示例 (Java HashSet to Array Example)

Sometimes we have to convert HashSet to array and vice versa. Below is a simple program showing correct way to convert HashSet to array and then Array to HashSet.

有时我们必须将HashSet转换为array,反之亦然。 下面是一个简单的程序,显示了将HashSet转换为array,然后将Array转换为HashSet的正确方法。

package com.journaldev.examples;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class HashSetToArrayExample {

	public static void main(String[] args) {
		Set<Integer> ints = new HashSet<>();
		for(int i=0; i<10; i++){
			ints.add(i);
		}
		System.out.println("ints set = "+ints);
		
		// set to array example
		Integer[] intArray = new Integer[ints.size()];
		intArray = ints.toArray(intArray);
		System.out.println("intArray = "+Arrays.toString(intArray));
		ints.remove(0);ints.remove(1);
		System.out.println("intArray = "+Arrays.toString(intArray));
		
		
		//array to set example
		ints = new HashSet<>(Arrays.asList(intArray));
		System.out.println("ints from array = "+ints);
		ints.remove(0);ints.remove(1);
		System.out.println("ints from array after remove = "+ints);
		System.out.println("intArray = "+Arrays.toString(intArray));


	}

}

Output of above HashSet to array example is;

以上HashSet的输出到数组示例为;

ints set = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
intArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
intArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ints from array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ints from array after remove = [2, 3, 4, 5, 6, 7, 8, 9]
intArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Java HashSet列出示例 (Java HashSet to List Example)

There is not much difference between Set and List, but sometimes we have to convert from Set to List or List to Set. Below is a simple example showing correct way to convert Set to List and then List to Set in java.

Set和List之间没有太大区别,但是有时我们必须从Set转换为List或List转换为Set。 下面是一个简单的示例,显示了在Java中将Set转换为List然后将List转换为Set的正确方法。

package com.journaldev.examples;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class HashSetToListExample {

	public static void main(String[] args) {
		Set<String> vowels = new HashSet<>();
		vowels.add("a"); vowels.add("e"); vowels.add("i");
		
		//set to list example
		List<String> vowelsList = new ArrayList<>(vowels);
		System.out.println("vowels set = "+vowels);
		System.out.println("vowelsList = "+vowelsList);
		
		vowels.add("o");
		vowelsList.add("a");vowelsList.add("u");
		System.out.println("vowels set = "+vowels);
		System.out.println("vowelsList = "+vowelsList);
		
		//list to set example
		vowels = new HashSet<>(vowelsList);
		System.out.println("vowels set = "+vowels);
		
	}

}

Output of above java Set to List example program is;

上面的java Set to List示例程序的输出是;

vowels set = [a, e, i]
vowelsList = [a, e, i]
vowels set = [a, e, i, o]
vowelsList = [a, e, i, a, u]
vowels set = [a, e, u, i]

Java HashSet equals()和hashCode()方法 (Java HashSet equals() and hashCode() methods)

HashSet utilise HashMap for storing it’s elements. HashSet works with equals() and hashCode() method to check for duplicate element when you try to add an element. Let’s see what happens if you Set object doesn’t provide equals() method implementation.

HashSet利用HashMap来存储其元素。 当您尝试添加元素时,HashSet与equals()和hashCode()方法一起使用以检查重复的元素。 让我们看看如果您的Set对象不提供equals()方法的实现会发生什么。

package com.journaldev.examples;

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

public class HashSetEqualsMethodImportance {

	public static void main(String[] args) {

		Set<Emp> emps = new HashSet<>();
		emps.add(new Emp(1,"Pankaj"));
		emps.add(new Emp(2, "David"));
		emps.add(new Emp(1, "Pankaj"));
		
		System.out.println(emps);
	}

}

class Emp {
	private String name;
	private int id;

	public Emp(int i, String n) {
		this.id = i;
		this.name = n;
	}
	
	@Override
	public String toString(){
		return "{"+id+","+name+"}";
	}
}

When we run above program, we get below output for Set elements.

当我们在程序上方运行时,将在Set元素的输出下方得到结果。

[{2,David}, {1,Pankaj}, {1,Pankaj}]

So it looks like we were able to store duplicate elements in the Set. Actually not, it’s happening because Emp class doesn’t define equals() method, so Object class equals() method implementation is used. Object class defines equals() method like below.

因此,看来我们能够在Set中存储重复的元素。 实际上不是这样,因为Emp类没有定义equals()方法,所以使用Object类的equals()方法实现。 对象类定义如下的equals()方法。

public boolean equals(Object obj) {
        return (this == obj);
    }

So when adding a new element, object reference is being checked rather than content. Hence we have objects with duplicate content, however they are having different references. Let’s see what happens when we define hashCode() and equals() methods in the Emp class.

因此,在添加新元素时,将检查对象引用而不是内容。 因此,我们的对象具有重复的内容,但是它们具有不同的引用。 让我们看看在Emp类中定义hashCode()和equals()方法时会发生什么。

package com.journaldev.examples;

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

public class HashSetEqualsMethodImportance {

	public static void main(String[] args) {

		Set<Emp> emps = new HashSet<>();
		emps.add(new Emp(1,"Pankaj"));
		emps.add(new Emp(2, "David"));
		emps.add(new Emp(1, "Pankaj"));
		
		System.out.println(emps);
		
		Emp e = new Emp(3, "Lisa");
		emps.add(e);
		System.out.println(emps);
		
		//set values to make it duplicate
		e.setId(1);
		System.out.println(emps);
		e.setName("Pankaj");
		System.out.println(emps);
	}

}

class Emp {
	private String name;
	private int id;

	public Emp(int i, String n) {
		this.setId(i);
		this.setName(n);
	}
	
	@Override
	public boolean equals(Object obj){
		if(obj == null || !(obj instanceof Emp)) return false;
		Emp e = (Emp) obj;
		if(e.getId() == this.getId() && this.getName().equals(e.getName())) return true;
		return false;
	}
	
	@Override
	public int hashCode(){
		return getId();
	}
	
	@Override
	public String toString(){
		return "{"+getId()+","+getName()+"}";
	}

	public String getName() {
		return name;
	}

	public int getId() {
		return id;
	}

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

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

}

This time our program produces following output.

这次我们的程序产生以下输出。

[{1,Pankaj}, {2,David}]
[{1,Pankaj}, {2,David}, {3,Lisa}]
[{1,Pankaj}, {2,David}, {1,Lisa}]
[{1,Pankaj}, {2,David}, {1,Pankaj}]

Notice that HashSet was able to check for duplicate when we tried to add an element. But we can change the object values using setter methods and make it duplicate. It worked because there is no operation done on Set. This is why Immutable objects works better with Set and Map.

请注意,当我们尝试添加元素时,HashSet能够检查重复项。 但是我们可以使用setter方法更改对象值并将其复制。 之所以起作用,是因为对Set没有执行任何操作。 这就是为什么不可变对象与Set和Map更好地工作的原因。

That’s all for Java HashSet example tutorial, I hope that all the important things are covered for HashSet in Java. If I have missed anything, please let me know through comments and I will try to add that too.

Java HashSet示例教程就这些了,我希望Java中的HashSet涵盖所有重要的内容。 如果我错过了任何事情,请通过评论告知我,我也会尝试添加。

翻译自: https://www.journaldev.com/11627/java-hashset

java中hashset

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值