Set集合,类似于一个罐子,程序可以把多个对象"丢进"Set集合,而Set集合通常不能记住每个元素的添加顺序.Set集合与Collection基本相同,没有提供任何额外的方法.实际上Set就是Collection,只是行为有所不同(Set不允许有重复元素)

  Set集合不允许包含相同的元素,如果试图把两个相同的元素添加入同一个Set集合中,则添加操作失败,add()返回false,且新元素不会被加入.

  上面介绍Set的通用知识,因此完全适合后面介绍的HashSet,TreeSet和EnumSet三个实现类,只是这三个实现类各有特色.

一  HashSet

  HashSet是Set接口的典型实现,大多数时候使用的Set集合时就是使用这个实现类.HashSet按Hash算法来存储集合中的元素,因此具有良好的存取和查找性能。

  HashSet具有以下特点:

    1.不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。

    2.HashSet不是同步的,如果多个线程同时访问一个HashSet。假设有两个或者以上的线程同时修改了HashSet集合时,则必须通过代码来保证其同步。

    3.集合元素可以是null.

  当使用HashSet集合来存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode()值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals()方法比较返回true,但是它们的hashCode()方法返回值不相等,HashSet将会把它们存入不同的位置,依然可以添加成功。

  也就是说,HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

示例代码:类A,B,C,分别重写了equals()方法,hashCode()方法这两个中的一个或者两个。

package com.j1803.collectionOfIterator;

import java.util.HashSet;
import java.util.Set; //类A重写了equals()方法,总是返回true,但没有重写hashCode()方法.
class A{
@Override
public boolean equals(Object obj){
return true;
}
} //类B重写了hashCode()方法,总是返回2,但没有重写equals()方法
class B{
@Override
public int hashCode(){
return 2;
}
}
//类C重写了equals()方法,总是返回true,重写了hashCode()方法,总是返回2
class C{
@Override
public boolean equals(Object obj){
return true;
}
@Override
public int hashCode(){
return 2;
}
}
public class HashSetTest {
public static void main(String[] args) {
Set book=new HashSet();
HashSet books=new HashSet();
A a=new A();
B b=new B();
C c=new C();
books.add(a);
books.add(a);
books.add(b);
books.add(b);
books.add(c);
books.add(c);
System.out.println(books); }
}
[com.j1803.collectionOfIterator.B@2, com.j1803.collectionOfIterator.A@4554617c] Process finished with exit code 0
package com.j1803.collectionOfIterator;

import java.util.HashSet;
import java.util.Set; //类A重写了equals()方法,总是返回true,但没有重写hashCode()方法.
class A{
@Override
public boolean equals(Object obj){
return true;
}
} //类B重写了hashCode()方法,总是返回2,但没有重写equals()方法
class B{
@Override
public int hashCode(){
return 2;
}
}
//类C重写了equals()方法,总是返回true,重写了hashCode()方法,总是返回2
class C{
/* @Override
public boolean equals(Object obj){
return true;
}*/
@Override
public int hashCode(){
return 2;
}
}
public class HashSetTest {
public static void main(String[] args) {
Set book=new HashSet();
HashSet books=new HashSet();
A a=new A();
B b=new B();
C c=new C();
books.add(a);
books.add(a);
books.add(b);
books.add(b);
books.add(c);
books.add(c);
book.add(new A());
book.add(new A());
book.add(new B());
book.add(new B());
Boolean flag1=book.add(new C());
System.out.println(flag1);
Boolean flag2=book.add(new C());
System.out.println(flag2);
System.out.println(book);
System.out.println(books); }
}
true
true
[com.j1803.collectionOfIterator.B@2, com.j1803.collectionOfIterator.B@2, com.j1803.collectionOfIterator.C@2, com.j1803.collectionOfIterator.C@2, com.j1803.collectionOfIterator.A@74a14482, com.j1803.collectionOfIterator.A@1540e19d]
[com.j1803.collectionOfIterator.B@2, com.j1803.collectionOfIterator.C@2, com.j1803.collectionOfIterator.A@4554617c]

Process finished with exit code 0

   

package com.j1803.setTest;
import java.util.HashSet;
class A{
@Override
public boolean equals(Object arg0) {
// TODO Auto-generated method stub
return true;
}
}
class B{ @Override
public int hashCode() {
// TODO Auto-generated method stub
return 2;
} }
class C{ @Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return true;
} @Override
public int hashCode() {
// TODO Auto-generated method stub
//注意hashCode()返回为1不是与B类中一样返回为2
return 1;
}
}
public class HashSetTest { public static void main(String[] args) {
HashSet books1=new HashSet();
books1.add(new A());
books1.add(new A()); books1.add(new B());
books1.add(new B()); books1.add(new C());
books1.add(new C());
System.out.println(books1); }
[com.j1803.setTest.A@7852e922, com.j1803.setTest.C@1, com.j1803.setTest.B@2, com.j1803.setTest.B@2, com.j1803.setTest.A@4e25154f]

     注意点:当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals()方法,则也应该重写其hashCode()方法。规则是:如果两个对象通过equals()方法比较返回true,则这两个对象的hashCode()值也应该相同。

    如果两个对象通过equals()方法比较返回true,但这两个对象的hashCode()方法返回值不同,这将导致HashSet会把这两个对象保存在Hash表中不同的位置,从而使两个对象都可以添加成功这就与Set集合的规则相冲突了,

    如果两个对象的hashCode()方法返回的hashCode()值相同,但它们通过equals()方法比较返回false时将更麻烦:因为两个对象的hashCode()值相同,HashSet将试图将它们保存在同一个位置,但又不行(否则只剩下一个对象)所以在实际上会在这个位置用链式结构来保存多个对象;而HashSet访问集合元素时也是根据元素的hashCode值来快速定位的,如果HashSet中两个以上的元素具有相同的hashCode值,将导致性能下降。

  hashCode()方法对于HashSet的重要性(实际上,对象的hashCode值对于后面的HashMap同样重要),下面给出重写hashCode()方法的基本原则。

  在程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值。

  当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法也应该返回相等的值。

  对象中用作equals()方法比较标准的实例变量,都应该用于计算hashCode值。

下面给出重写hashCode()方法的一般几个步骤。

二  LinkedHashSet类

HashSet还有一个子类LinkedHashSet,LinkHashSet集合也是根据元素的hashCode的值来决定元素的存储位置的,但它使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。也就是说,当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按照元素的添加顺序来访问集合里的元素。

  LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时将有很好的性能,因为它是以链表来维护内部顺序的。

package com.j1803.setTest;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
public static void main(String[] args) {
LinkedHashSet book=new LinkedHashSet();
book.add("AAAAA");
book.add("BBBBB");
book.add("CCCCC");
book.add("DDDDD");
System.out.println(book);
} }
[AAAAA, BBBBB, CCCCC, DDDDD]

  输出LinkedHashSet集合的元素时,元素的顺序总是与添加顺序一致。

  虽然LinkedHashSet使用了链表记录集合元素的添加顺序,但LinkedHashSet依然是HashSet,因此它依然不允许集合元素重复。

三  TreeSet类

  TresSet是SortedSet接口的实现类,正如SortedSet名字所暗示的,TreeSet可以确保集合元素处于排序状态。与HashSet集合相比,TreeSet还提供了如下几个额外的方法

  Comparator comparator():如果TreeSet采用了定制排序,则该方法返回定制排序所使用的Comparator;如果TreeSet采用了自然排序,则返回null.

  Object first():返回集合的第一个元素。

  Object last():返回集合中的最后一个元素。

  Object lower(Object e):返回集合中位于指定元素之前的元素(也就是小于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素)。

  Object higher(Object e):返回集合中位于指定元素之后的元素(也就是大于指定元素的最小元素,参考元素不需要是TreeSet集合里的元素)。

  Object subSet(Object fromElement,Object toElement):返回此Set的子集合,范围从fromElement(包含)到toElement(不包含)。

  SortedSet headSet(Object toElement):返回此Set集合的子集,由小于toElement的元素组成。

  SortedSet tailSet(Object fromElement):返回此Set集合的子集,由大于或等于fromElement的元素组成。

package com.j1803.setTest;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
TreeSet num=new TreeSet();
num.add(-5);
num.add(45);
num.add(78);
num.add(-13);
num.add(40);
num.add(99);
num.add(0);
System.out.println(num);
//输出集合的第一个元素
System.out.println("输出集合的第一个元素"+num.first());
//输出集合的最后一个元素
System.out.println("输出集合的最后一个元素"+num.last());
//输出小于50最大的元素
System.out.println("输出小于50的最大的元素"+num.lower(50));
//输出大于50的最小元素
System.out.println("输出大于50的最小元素"+num.higher(50));
//输出50到80之间的元素
System.out.println("输出10到80之间的元素"+num.subSet(10, 80));
//输出小于50的元素treeSet集合
System.out.println("输出小于50的元素"+num.headSet(50));
//输出大于50的元素的treeSet集合
System.out.println("输出大于50的元素的treeSet集合"+num.tailSet(50));
}
}
[-13, -5, 0, 40, 45, 78, 99]
输出集合的第一个元素-13
输出集合的最后一个元素99
输出小于50的最大的元素45
输出大于50的最小元素78
输出10到80之间的元素[40, 45, 78]
输出小于50的元素[-13, -5, 0, 40, 45]
输出大于50的元素的treeSet集合[78, 99]

TreeSet并不是根据元素的插入顺序来排序的,而是根据元素实际值的大小来进行排序的。

与HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合数据。TreeSet支持两种排序方法:自然排序和定制排序,默认为自然排序。

  1.自然排序

  TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系。然后将集合元素按照升序排列,这种方式就是自然排序。

  Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现了该接口的类的对象就可以比较大小。当一个对象调用该方法与另一个对象进行比较是。例如obj1.compareTo(obj2),如果改方法返回0,则表明这两个对象相等,如果该方法返回一个正整数,则表明obj1大于obj2;如果该方法返回一个负整数,则表明obj1小于obj2.

  Java的一些常用类已经实现了Comparable接口,并提供了比较大小的标准。下面是实现了Comparable接口的常用类。

  BigDecimal,Character,Boolean,String,Date,Time.

  如果把一个自定义的类的对象添加到treeSet中,则该对象对应的类必须实现Comparable接口,否则程序将会抛出异常ClassCastException.

  大部分类在实现compareTo(Object obj)方法时,都需要将被比较对象obj强制类型转换成相同类型,因为只有相同类的两个实例才会比较大小。

  如果向TreeSet中添加的对象是程序员自定义的类的对象,则可以向TreeSet中添加多种类型的对象,前提是用户自定义的类实现了Comparable接口,且实现compareTo(Object obj)方法没有进行强制类型转换。但是当试图取出TreeSet集合元素时,不同类型的元素依然会发生ClassCastException异常。

  总结:如果希望TreeSet能正常运作,TreeSet只能添加同一种类型的对象。

  当一个对象加入TreeSet集合中时,TreeSet调用该对象的compareTo(Object obj)方法与容器中的其他对象比较,然后根据红黑树结构找到它的存储位置。如果两个对象通过compareTo(Object obj)方法比较相等,新对象将无法添加到TreeSet集合中。

  对于TreeSet集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj)方法比较是否返回0,如果返回0,则认为相等,否则就认为它们不相等。

package com.j1803.setTest;

import java.util.TreeSet;

/**
* @author zhou_oyster
*
*/
class Person implements Comparable{
private int age;
@Override
public boolean equals(Object obj) {
return true;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Object arg0) {
return 1;
}
public Person(int age) {
super();
this.age = age;
}
}
public class TreeSetTest1 {
public static void main(String[] args) {
TreeSet book=new TreeSet();
Person person=new Person(45);
book.add(person);
System.out.println(book.add(person));//输出true,添加成功
System.out.println(book);//显示所有的元素
//取出book集合中的第一个元素并修改年龄
((Person)book.first()).setAge(12);
//查看第一个元素的年龄和最后一个元素的年龄
System.out.println(((Person)book.first()).getAge()+"===================="+((Person)book.last()).getAge());
} }
true
[com.j1803.setTest.Person@7852e922, com.j1803.setTest.Person@7852e922]
12====================12

  可以看到虽然修改Comparable的compareTo()方法,误让程序以为person和他本身不相等,从而可以添加成功,集合中保存对象的引用指的是同一个对象,所以修改了第一个age,后面的age也修改了。

  故:当需要把一个对象放入TreeSet中,重写该对象对应类的equals()方法时,应保证该方法与compareTo(Object obj)方法有一致结果,其规则是:如果两个对象通过equals()方法比较返回true,这两个对象通过compareTo()方法应该返回0.

  反之如果compareTo(Object obj)返回0而equals()返回false,则会与Set规则产生冲突。

  如果向TreeSet中添加了可变对象,并且后面的程序修改了该可变对象的实例变量,将导致它与其他对象的大小顺序发生了改变,但TreeSet不会再次调整它们的顺序,甚至可能导致TreeSet中保存的这两个对象通过compareTo(Object obj)方法比较返回0.

package com.j1803.setTest;
import java.util.TreeSet;
public class Book implements Comparable{
private int price;
public Book(int price) {
super();
this.price = price;
}
@Override
public String toString() {
return "Book [price=" + price + "]";
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (price != other.price)
return false;
return true;
}
@Override
public int compareTo(Object obj) {
Book book=(Book)obj;
return this.price>book.getPrice()?1:this.price<book.getPrice()?-1:0;
}
public static void main(String[] args) {
TreeSet set=new TreeSet();
set.add(new Book(12));
set.add(new Book(10));
set.add(new Book(-10));
set.add(new Book(-5));
set.add(new Book(5));
set.add(new Book(8));
//打印set集合
System.out.println(set);
//修改第一个元素
Book book1=(Book)set.first();
book1.setPrice(13);
//修改最后一个元素,使其与第二个元素的price相同
Book book2=(Book)set.last();
book2.setPrice(-5);
//打印,可以看到无序且有重复元素
System.out.println(set);
//删除实例变量被改变的元素,删除失败。
System.out.println(set.remove(new Book(13)));
//打印
System.out.println(set);
//删除实例变量没有被改变的元素,删除成功。
System.out.println(set.remove(new Book(10)));
//打印
System.out.println(set);
} }
[Book [price=-10], Book [price=-5], Book [price=5], Book [price=8], Book [price=10], Book [price=12]]
[Book [price=13], Book [price=-5], Book [price=5], Book [price=8], Book [price=10], Book [price=-5]]
false
[Book [price=13], Book [price=-5], Book [price=5], Book [price=8], Book [price=10], Book [price=-5]]
true
[Book [price=13], Book [price=-5], Book [price=5], Book [price=8], Book [price=-5]]

  可以删除没有被修改实例变量,且不与其他修改实例变量的对象重复的对象。

  当执行了红色代码后TreeSet会对集合中的元素重新索引(不是重新排序),接下来可以删除TreeSet所有元素,推荐不要修改放入HashSet和TreeSet集合中元素的关键实例变量。

    //删除元素
System.out.println(set.remove(new Book(-5)));
System.out.println(set);
[Book [price=13], Book [price=-5], Book [price=5], Book [price=8], Book [price=-5]]
true
[Book [price=13], Book [price=5], Book [price=8], Book [price=-5]]

  2.定制排序

  TreeSet的自然排序是根据元素的大小,TreeSet将它们以升序排列。如果需要实现定制排序,例如以降序排列。则可以通过Comparator接口的帮助。,该接口里包含了一个int compare(T o1,T o2)方法。该方法用于比较o1和o2的大小:如果该方法中返回正整数,则表明o1大于o2;如果该方法返回0,则表明o1等于o2;如果该方法返回负整数,则表明o1大于o2.

  如果需要实现定制排序,则需要在创建TreeSet集合对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。由于Comparator是一个函数式接口,因此可用Lambda表达式来代替Comparator对象。

四  EnumSet类

  EnumSet是一个专为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值。该枚举类型在创建EnumSet时显示或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。

  EnumSet在内部以位向量的形式存储,这种存储方式非常紧凑,高效,因此EnumSet对象占用内存很小,而且运行效率很好。尤其是进行批量操作(如调用containsAll()和remainAll()方法)时,如果其参数也是EnumSet集合,则该批量操作的执行速度也非常快。

  EnumSet集合不允许加入null元素,如果试图插入null元素,EnumSet将抛出NullPointException异常。如果只是想判断EnumSet是否包含null元素或者试图删除null元素都不会抛出异常,只是删除操作将返回false,因为没有任何null元素被删除。

  EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的类方法来创建EnumSet对象。EnumSet类它提供了如下常用的类方法来创建EnumSet对象。

  EnumSet allOf(Class elementType):创建一个包含指定枚举类里所有枚举值的EnumSet集合.

  EnumSet complementOf(Enumset s):创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的,此枚举类剩下的枚举值(也就是新EnumSet集           合和原来EnumSet集合的集合元素加起来都是该枚举类的所有枚举值)。

  EnumSet copyOf(Collection c):使用一个普通集合来创建EnumSet集合。

  EnumSet copyOf(EnumSet s):创建一个与指定EnumSet具有相同元素类型,相同集合元素的EnumSet集合。

  EnumSet noneOf(Class elementType):创建一个元素类型为指定枚举类型的空EnumSet.

  EnumSet of(E first,E...rest):创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。

  EnumSet range(E from,E to):创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。

package com.j1803.EnumSetTest1;
import java.util.EnumSet;
enum Season{
SPRING,SUMMER,FALL,WINTER
}
public class EnumSetTest {
public static void main(String[] args) {
//创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值。
EnumSet esl= EnumSet.allOf(Season.class);
//输出[SPRING,SUMMER,FALL,WINTER]
System.out.println(esl);
//创建一个EnumSet空集合,指定集合元素是Season类的枚举值。
EnumSet es2=EnumSet.noneOf(Season.class);
//输出[]
System.out.println(es2);
//手动添加元素。
es2.add(Season.FALL);
es2.add(Season.SPRING);
//输出[FALL,SPRING]
System.out.println(es2);
//以指定枚举值创建EnumSet集合
EnumSet es3=EnumSet.of(Season.SUMMER,Season.FALL,Season.WINTER);
//输出[SUMMER,FALL,WINTER]
System.out.println(es3);
EnumSet es4=EnumSet.of(Season.SUMMER,Season.WINTER);
//新创建的EnumSet集合元素和es4集合元素有相同的类型
//es5集合元素+es4集合元素=Season枚举类的全部枚举值
EnumSet es5= EnumSet.complementOf(es4);
System.out.println(es5);
}
}
[SPRING, SUMMER, FALL, WINTER]
[]
[SPRING, FALL]
[SUMMER, FALL, WINTER]
[SPRING, FALL]

要求复制另一个Collection集合中的所有元素到新创建的

package com.j1803.EnumSetTest1;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
enum Season{
SPRING,SUMMER,FALL,WINTER
}
public class EnumSetTest {
public static void main(String[] args) {
Collection c1=new HashSet();
c1.add(Season.SUMMER);
c1.add(Season.SPRING);
c1.add(Season.FALL);
//复制Collection集合中的所有元素来创建EnumSet集合
EnumSet enumSet= EnumSet.copyOf(c1);
//输出[SUMMER,SPRING,FALL]
System.out.println(enumSet);
//运行报ClassCastException错误
//enumSet.add("PHP");
//enumSet.add("C++");
enumSet.add(Season.WINTER);
System.out.println(enumSet);
}
}
[SPRING, SUMMER, FALL]
[SPRING, SUMMER, FALL, WINTER]

五  各Set实现类的性能分析

  HashSet与TreeSet:HashSet的性能是比TreeSet要好,因为TreeSet需要额外的红黑树算法来维护集合元素的次序,当需要一个注重保持排序的Set时,才使用TreeSet。

  EnumSet是所有Set实现类中性能最好的,但它只能保持同一个枚举类的枚举值作为集合元素。

  HashSet,TreeSet和EnumSet都是线程不安全的。如果有多个线程同时访问一个Set集合,并且有超过一个线程修改了该Set集合,则必须手动保证该Set集合的同步性。通常可以通过Collection工具类的synchronizedSortedSet方法来"包装"该Set集合。在创建时进行,以防止对Set集合的意外非同步访问。

SortedSet sortedSet= Collections.synchronizedSortedSet(new TreeSet());

  

java集合(4)-Set集合的更多相关文章

  1. Java常用的几种集合, Map集合,Set集合,List集合

    Java中  Object是所有类的根 Java集合常用的集合List集合.Set集合.Map集合 Map接口常用的一些方法 size() 获取集合中名值对的数量 put(key k, value v ...

  2. Java基础加强之集合篇(模块记忆、精要分析)

    千里之行,始于足下.把别人的变成自己,再把自己的分享给别人,这也是一次提升的过程.本文的目的是以一篇文章从整体把握集合体系又不失一些细节上的实现,高手路过. 集合的作用与特点 Java是一门面向对象语 ...

  3. Java中如何克隆集合——ArrayList和HashSet深拷贝

    编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法.需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味 ...

  4. Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList

    概要 本章是"JUC系列"的CopyOnWriteArrayList篇.接下来,会先对CopyOnWriteArrayList进行基本介绍,然后再说明它的原理,接着通过代码去分析, ...

  5. Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet

    概要 本章是JUC系列中的CopyOnWriteArraySet篇.接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解 ...

  6. Java多线程系列--“JUC集合”04之 ConcurrentHashMap

    概要 本章是JUC系列的ConcurrentHashMap篇.内容包括:ConcurrentHashMap介绍ConcurrentHashMap原理和数据结构ConcurrentHashMap函数列表 ...

  7. Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListMap类进行详细的介绍.内容包括:ConcurrentSkipListMap介绍ConcurrentSki ...

  8. Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListSet类进行详细的介绍.内容包括:ConcurrentSkipListSet介绍ConcurrentSki ...

  9. Java多线程系列--“JUC集合”07之 ArrayBlockingQueue

    概要 本章对Java.util.concurrent包中的ArrayBlockingQueue类进行详细的介绍.内容包括:ArrayBlockingQueue介绍ArrayBlockingQueue原 ...

  10. Java多线程系列--“JUC集合”08之 LinkedBlockingQueue

    概要 本章介绍JUC包中的LinkedBlockingQueue.内容包括:LinkedBlockingQueue介绍LinkedBlockingQueue原理和数据结构LinkedBlockingQ ...

随机推荐

  1. 太方便了!利用Python对批量Pdf转Word

    在wps或者office里面可以将pdf转word,不过只能免费转前面5页,超过5页就需要会员.今天教大家一个Python办公小技巧:批量Pdf转Word ,这样可以自由想转多少页都可以. 思路:这里 ...

  2. 在OpenShift平台上验证NVIDIA DGX系统的分布式多节点自动驾驶AI训练

    在OpenShift平台上验证NVIDIA DGX系统的分布式多节点自动驾驶AI训练 自动驾驶汽车的深度神经网络(DNN)开发是一项艰巨的工作.本文验证了DGX多节点,多GPU,分布式训练在DXC机器 ...

  3. the rust book 的简单入门笔记

    rust learning day 1 (2021/05/27) 学了常量,变量,数据类型,控制流,所有权 char 的宽度是4字节,一个 unicode 的宽度 控制流条件都不要括号 rust 中的 ...

  4. JVM集合之开篇点题

    大家在平时的开发过程中是否遇到过StackOverflowError.OutOfMemoryError等类似的内存溢出错误呢?大家又是怎么解决这个问题的?再来,大家在面试过程中有没有被面试官提问过jv ...

  5. Java SSM框架理论知识

    一.Spring理论知识 1.Spring 在ssm中起什么作用? Spring:轻量级框架 作用:Bean工厂,用来管理Bean的生命周期和框架集成. 两大核心:1.IOC/DI(控制反转/依赖注入 ...

  6. IDEA骚技巧

    1. var 声明 2. null 判空 3. notnull 判非空 4. nn 判非空 5. for 遍历 6. fori 带索引的遍历 7. not 取反 8. if 条件判断 9. cast ...

  7. 深入理解Faiss 原理&源码 (一) 编译

    目录 深入理解Faiss 原理&源码 (一) 编译 mac下安装 安装mac xcode工具包 安装 openblas 安装swig 安装libomp 编译faiss 附录 深入理解Faiss ...

  8. 学习响应式编程 Reactor (1) - 响应式编程

    响应式编程 命令式编程(Imperative Programing),是一种描述计算机所需做出的行为的编程范式.详细的命令机器怎么(How)去处理以达到想要的结果(What). 声明式编程(Decla ...

  9. 合宙Luat直播间即将开启,你揭开行业奥秘,让你快人一步。

    嗨~刚陪你们过儿童节 和你们一起成长的合宙Luat 又有新计划 -- 合宙Luat官方直播即将开启 - 敬请关注 - - 官方直播什么内容 - 可能是合宙研发动态 可能是新品发布资讯 可能是行业大咖分 ...

  10. VBS脚本编程(5)——过程与函数

    过程是构成程序的一个模块,往往用来完成一个相对独立的功能.过程可以使程序更清. Sub过程与Function函数的区别: Sub没有返回值,Function有返回值: Sub不能放在表达式中,Func ...