流年似水博客开通了,本站主要是写关于Web和大数据方面内容,正在更新中,欢迎大家光临!
  1. 文章:97 篇
  2. 总浏览:55,069 次
  3. 评论:22条
  4. 最后更新:2020-06-08
  5. 分类目录:39 个

Java之集合(Collection体系)详解

Java l, xy 959℃ 0评论

  1.   数组和集合对比

(1)      集合:保存一组相同数据类型的集合

(2)      数组:保存一组任意类型的集合

(3)      使用场景

1           一般来说基本数据类型存取一般使用数组,引用数据类型的操作存放一般使用集合

2           数据的个数确定的情况下,可以使用数组

(4)      集合的优点(相比于数组)

1           操作方便,集合提供大量的方法对其中的元素进行操作

2           相比于数组,不需要关心容量问题(可以自动扩容)

3           相比于数组,可以保存任意类型(不适用泛型的时候)

 

  1.   集合的体系图

  2.   Collection集合

(1)      特点:

1           单列集合---只能保存单一的值

(2)      常见方法(使用default修饰的方法为JDK8新增的默认方法

1           添加

1)         boolean add ( E e )

2)         boolean addAll( Collection<? extends E > c) 将集合c中的元素添加到本集合中

 

2           删除

1)         boolean remove(Object o)

2)         boolean removeAll(Collection<?> c) 删除本集合中与指定集合c中元素相匹配的所有元素

3)         default boolean removeIf(Predicate <? super E> filter)

4)         void clear()

3           判断

1)         boolean contains(Object obj)

2)         boolean containsAll(Collection<?> c) 判断本集合中元素是否全部包含指定集合c

3)         boolean equals(Object obj)

4)         booean isEmpty()

 

4           遍历

1)         Iterator<E> iterator()

5           获取

1)         int size()

6           转数组

1)         Object[] toArray()

2)         <T> T[] toArray(T[] a): 返回指定类型的数组。如果传入的数组长度小于集合的size,则返回集合中数组元素的数组,传入数组内的值不变;如果传入数组的长度大于或者等于集合的size,则将集合中的元素拷贝到传入的数组内(下标多余部分为null),并返回。

7           求交集

1)         boolean retainAll(Collection <?> c)  求本集合和指定集合c的交集,调用完成后,原集合会删除c集合中没有的元素;如果原集合和指定集合没有交集,则会清空原集合(删除所有的元素);如果原集合和指定集合元素相同,则不操作原集合。当原集合被修改返回true,否则返回false

8           获取流

1)         default Stream<E> stream()

2)         default Stream<E> parallelStream()

3)         default Spliterator<E> Spliterator()   jdk1.8中为并行遍历而设计的迭代器

方法测试:


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
* 测试Collection方法
*/
public class CollectionTest {

private Collection<String> collection = new ArrayList<>();
/**
* stringCollection集合不能新增、删除元素!
* 因为asList方法返回的ArrayList是Arrays类内部定义的,其内部维护的
* private final E[] a; 是使用final修饰的。
* */
private Collection<String> stringCollection = Arrays.asList("cc", "ee");
/**
* 公用方法:打印集合元素
*/
public static void printCollection(Collection<?> collection) {
for (Object s : collection) {
System.out.print(s + "\t");
}
}
/**
* 初始化collction集合
* */
@BeforeEach
public void beforeAll() {
collection.add("aa");
collection.add("bb");
collection.add("cc");
collection.add("cc");
}

/**
* 测试addAll()方法
*/
@Test
public void addAllTest() {
collection.addAll(stringCollection);
//结果:aa bb cc cc cc ee
printCollection(collection);
}
/**
*测试removeAll()方法
* */

@Test
public void removeAllTest() {
collection.removeAll(stringCollection);
//打印结果:aa bb
printCollection(collection);
}

/**
* 删除collection集合中为cc的元素
* removeIf测试
*/
@Test
public void removeIfTest() {
collection.removeIf((e) -> e.equals("cc"));
//打印结果:aa bb
printCollection(collection);
}

/**
* 测试containAll()方法
* */
@Test
public void containAllTest(){
boolean b = collection.containsAll(stringCollection);
//打印结果:false
System.out.println(b);
}

/**
* 测试retainAll()方法
* */
@Test
public void retainAllTest(){
boolean b = collection.retainAll(stringCollection);
//true
System.out.println(b);
//cc cc
printCollection(collection);
}

/**
* 测试toArray<T[] t)
* */
@Test
public void toArrayTest(){
String[] strings = new String[2];
String[] returnArray = collection.toArray(strings);
/******************数组小于集合的size************************/
for (String s : strings){
//打印: null null
System.out.print(s + "\t");
}
System.out.println();
for (String s : returnArray){
//打印:aa bb cc cc
System.out.print(s + "\t");
}
/******************数组大于或者等于集合的size************************/
System.out.println();
strings = new String[5];
returnArray = collection.toArray(strings);
for (String s : strings){
//打印: aa bb cc cc null
System.out.print(s + "\t");
}
System.out.println();
for (String s : returnArray){
//打印: aa bb cc cc null
System.out.print(s + "\t");
}
}

(3)      遍历方法

1           迭代器:

1)         特点: 遍历的时候可以删除集合中的元素,也可修改保存元素的内部的属性

2)         案例:


/**
* 测试遍历方式一
* 可以直接删除保存的元素(保存的地址)
*/
@Test
public void test2() {
Collection<String> collection = new ArrayList<>();
collection.add("aa");
collection.add("bb");
//遍历
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
//删除当前遍历元素
iterator.remove();
}

2           增强for

1)         特点:遍历的时候不能修改或者删除集合中的元素,只能修改元素内部的属性

2)         案例:


/**
* 测试遍历方式二: 增强for
* 不能修改原集合中的元素(保存的地址),
* 但是可以修改保存元素的属性
*/
@Test
public void test1() {
Collection<String> collection = new ArrayList<>();
collection.add("aa");
collection.add("bb");
//遍历
for (String s : collection) {
//不会修改集合中保存的元素
s = "你好";
System.out.println(s);
}
}

(4)      List集合

1           特点:

1)         保存元素有序(存入和取出的顺序一致)

2)         可以允许有重复元素

3)         具有索引

2           常见方法(使用default修饰的方法为JDK8新增的默认方法

1)         添加

  1. boolean addAll(int index,Collection<? extends E> c) :在指定为位置(index)插入集合c中的所有元素
  2. void add (int index,E element)

2)         修改

  1. default void replaceAll(UnaryOperator<T> operator) : 替换匹配的所有元素
  2. E set(int index,E element)

3)         删除

  1. E remove(int index)

4)         获取

  1. E get(int index)
  2. int indexOf(Object o)
  3. int lastIndexOf(Object o)
  4. List<E> subList(int fromIndex,int toIndex) : 前闭后开(包含fromIndex,不包含toIndex

5)         遍历

  1. ListIterator<E> listIterator()
  2. ListIterator<E> listIterator(int index) : (index的范围为: 0-size 包含size)

6)         排序

  1. default void sort(Comparator< ? super E> e)

         案例:


import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.*;

/**
* 测试List接口方法
*/
public class ListTest {

private List<String> list;

/**
* 初始化list
*/
@BeforeEach
public void indexOf() {
list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("bb");
list.add("cc");
}

/**
* 打印集合
*/
public static void printCollection(Collection<?> collection) {
for (Object o : collection) {
System.out.print(o + "\t");
}
}

/**
* 测试addAll(int index,Collection<? super E> c)
*/
@Test
public void addAll() {
List<String> stringList = new ArrayList<>();
stringList.add("qq");
stringList.add("ss");
list.addAll(1, stringList);
//打印结果:aa qq ss bb bb cc
printCollection(list);
}

/**
* 测试replaceAll
*/
@Test
public void replaceAllTest() {
//将list集合中所有的"bb"替换为"yy"
list.replaceAll((e) -> e.equals("bb") ? "yy" : e);
//打印结果:aa yy yy cc
printCollection(list);
}

/**
* 测试
* indexOf()
* lastIndexOf()
*/
@Test
public void indexOfTest() {
int indexOf = list.indexOf("bb");
int lastIndexOf = list.lastIndexOf("bb");
//indexOf = 1
System.out.println("indexOf = " + indexOf);
//lastIndexOf = 2
System.out.println("lastIndexOf = " + lastIndexOf);
}

/**
* 测试subList(int fromIndex,int toIndex)
*/
@Test
public void subListTest() {
List<String> stringList = list.subList(0, 2);
//打印结果:aa bb
printCollection(stringList);
}

/**
* 测试listIterator(int index)
* 目的:使用listIterator(int index)实现倒序遍历
*/
@Test
public void listIteratorTest() {
ListIterator<String> stringListIterator = list.listIterator(list.size());
for (; ; ) {
if (!stringListIterator.hasPrevious()) {
break;
}
String previous = stringListIterator.previous();
System.out.println(previous);
}
}
/**
* 测试sort(Comparator<? super E> c)
*
* 目的:使用sort方法对list集合进行倒序
* */
@Test
public void sortTest(){
//list.sort(String::compareTo);
list.sort((e1,e2)->-e1.compareTo(e2));
//打印结果:cc bb bb aa
printCollection(list);
}
}

 

3           遍历方式 (ListIterator迭代器)

1)         特点:

  1. Iterator迭代器增加了增加(add)、修改(set)、向上遍历(判断(hasPrevious)、获取值(previous)、获取上一个索引(previousIndex))方法、获取想一个索引方法(nextIndex

2)         使用:


/**
*
* 目的:倒序遍历集合
* */
ListIterator<String> stringListIterator = list.listIterator(list.size());

for (; ; ) {
//判断是否还有上一个元素
if (!stringListIterator.hasPrevious()) {
break;
}
//获取上一个元素的
String previous = stringListIterator.previous();
System.out.println(previous);
}

 

4           注意:

1)         List集合中保存的元素是数字类型,调用remove方法的时候如果直接传入int类型的值默认调用的E remove(int index)方法,因为此方法最匹配。千万别以为是调用 boolean remove(Object obj),否则会报java.lang.IndexOutOfBoundsException异常


/**
* 测试List集合中保存数值类型调用remove(index index)方法出现的问题
*/
@Test
public void listTest() {
List<Integer> list = new ArrayList<>();
list.add(94);
list.add(12);
list.add(11);
//报错:java.lang.IndexOutOfBoundsException: Index: 12, Size: 3
//这里是调用 E remove(int index)方法
list.remove(12);
printCollection(list);


/**************调用boolean remove(Object obj)的正确写法 ***************/
list.remove(Integer.valueOf(12));
printCollection(list);

}

5           常见的实现类

1)         ArrayList

  1. 特点

a)         JDK1.2以后推出,用来替代Vector

b)        内部实现使用可变数组数据结构

c)         线程不安全的

  1. 常用方法(以下方法调用过程中,不能对集合进行任何操作(获取操作除外))

a)         public void forEach(Consume<? super E> action ) 遍历集合中的元素,遍历过程中不能对集合进行其他操作,否则报ConcurrentModificationException异常

b)        public boolean removeIf(Predicate<? super E> filter):删除符合条件的元素,删除成功返回true,否则返回false。注意:删除成功以后,ArrayList内维护的elementData数组的长度不会发生变化

c)         public void replaceAll(UnaryOperator<E> operator) : 替换符合条件的所有元素

  1. 遍历方式

a)         List

  1. 底层实现:

a)         维护属性

  1. 核心属性elementData,是一个Object[]数组,用于保存元素



/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added. // 内部保存元素的数组
*/
transient Object[] elementData; // non-private to simplify nested class access
  1. 默认初始化数组容量DEFAULT_CAPACITY值为10



/**
* Default initial capacity. 默认初始化容量
*/
private static final int DEFAULT_CAPACITY = 10;
  1. 空的Object数组EMPTY_ELEMENTDATA,值为{}



/**
* Shared empty array instance used for empty instances. 为空实例准备的空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};

 

  1. 默认容量的空Object数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,默认为{}

 


/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added. 为默认大小容量实例准备的空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  1. 维护表示保存元素个数的变量size



/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
  1. 维护记录ArrayList内部结构变化次数的modCount

protected transient int modCount = 0;

b)        构造器

  1. 无参构造 public ArrayList();

i)           默认初始化elementDataDEFAULTCAPACITY_EMPTY_ELEMENTDATA

/**
* Constructs an empty list with an initial capacity of ten.

*/
public ArrayList() {
    this.elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}



/**
* Constructs an empty list with an initial capacity of ten.     构造一个空的List,注意:此时并没有初始化容量为10。

实际上扩容是在第一次调用add方法的时候才会扩容为10

*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

 

  1. 初始化容量构造器public ArrayList(int initialCapacity);

i)           初始化指定容量的elementData,如果initialCapacity大于0,直接初始化为指定长度;如果等于0,初始化为EMPTY_ELEMENTDATA;如果小于0,报异常。


/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) { //容量大于0,直接初始化为指定initialCapacity的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) { //容量等于0,将EMPTY_ELEMENTDATA赋值给elementData 
this.elementData = EMPTY_ELEMENTDATA;
} else { //容量小于0,抛异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}

 

  1. 初始化保存数据的构造器public ArrayList(Collection<? extends E> c)

i)           如果cnull,报空指针异常

ii)         如果csize0,则初始化elementDataEMPTY_ELEMENTDATA

iii)       如果csize大于0,则将c集合转换为数组并拷贝一份赋值给elementData


/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}

 

c)         扩容机制

  1. 判断内部维护的elementData是否是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,如果是,执行②;否则执行③。
  2. 求出DEFAULT_CAPACITY10)和 size +1 的最大值。modCount++,然后判断求的的最大值,判断最大值是否大于当前elementData的长度,如果大于,则扩容(将求的最大值传入grow()方法扩容;
  3. modCount++,判断size+1是否大于elementData的长度,如果大于则扩容(将size + 1传入grow()方法扩容)
  4. 扩容:

i)           确定扩容以后新数组长度newCapacity(元素数组的1.5倍)

ii)         判断新数组长度newCapacity是否小于传入长度,如果小于则将newCapacity赋值为传入的长度

iii)       判断newCapacity是否大于MAX_ARRAY_SIZE,如果大于则将newCapacity赋值符Integer.MAX_VALUE

iv)       创建长度为newCapacity数组,将旧数组的保存的值拷贝的新数组

  1. 将保存的值添加到elementData对应的位置上
  2. 下面是扩容源码


/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}


private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}

ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
modCount++;

// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

 

2)         LinkedList

  1. 特点

a)         使用双向链表实现

b)        线程不安全

c)         可实现队列特点

  1. 常用方法

a)         新增

  1. 1.2版本

i)           public void addFirst(E e)

ii)         public void addLast(E e)

  1. 1.5版本

i)           public boolean offer(E e) 添加元素到链表尾部,底层调用add(E e )方法

  1. 1.6版本

i)           public boolean offerFirst(E e) :添加元素到链表头部,底层调用addFirst(E e)方法

ii)         public boolean offerLast(E e):添加元素到链表尾部,底层调用addLast(E e)

iii)       public void push(E e): 添加元素到链表头部,底层调用addFirst(E e)

b)        删除

  1. 1.2版本

i)           public E removeFirst()

ii)         public E removeLast()

  1. 1.5版本

i)           public E poll() 删除链表头部元素,如果头元素为null,则返回null

ii)         public E remove() 删除链表头部元素,底层调用removeFirst()

  1. 1.6版本

i)           public E pollFirst(): 删除链表头部元素

ii)         public E pollLast(): 删除链表尾部元素

iii)       public E pop():删除链表头部元素,底层调用removeFirst()方法

iv)       public boolean removeFirstOccurrence(Object o) : 删除链表中第一个与o匹配的元素(从头到尾),删除成功返回true,链表中不包含返回false

v)         public boolean removeLastOccurrence(Object o) :删除链表中第一个与o匹配的元素(从尾到头),删除成功返回true,链表中不包含返回false

vi)        

c)         获取

  1. 1.2版本

i)           public E getFirst()

ii)         public E getLast()

  1. 1.5版本

i)           public E peek() 获取链表头部元素

ii)         public E element() 获取链表头部元素,底层调用getFirst()方法

iii)        

  1. 1.6版本

i)           public E peekFirst(): 获取链表头部元素

ii)         public E peekLast():获取链表尾部元素

  1.  

d)        遍历

  1. public Iterator<E> decendingIterator():获取倒序迭代器,用于倒序遍历

e)         克隆

  1. public Object clone() 获取一个LinkedList的浅拷贝
  1. 遍历方式

a)         多了一个倒序遍历 


LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("aa");
linkedList.add("bb");
linkedList.add("cc");
//倒序遍历
Iterator<String> stringIterator = linkedList.descendingIterator();
while(stringIterator.hasNext()){
String str = stringIterator.next();
//打印结果:cc bb aa
System.out.print(str + "\t");
}
  1. 源码分析

a)         内部维护属性

  1. int size :保存元素个数
    transient int size = 0;
  1. Node<E>  first:指向第一个元素

/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null) // 指向双向链表的头节点
*/
transient Node<E> first;

 

  1. Node<E>  last:指向最后一个元素


/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null) // 指向双向链表的尾节点
*/
transient Node<E> last;

  1. int modCount:记录内部结构修改次数
protected transient int modCount = 0;

b)        维护节点  Node内部类,实现双向链表结构


private static class Node<E> {
E item; // 保存元素(数据)
Node<E> next; // 指向下一个节点
Node<E> prev; // 指向前一个节点

Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

 

 

  1. 注意事项

a)         LinkedList类中提供1.2版本中提供的删除(removeFirstremoveLast)、获取(getFirstgetLast)方法在链表为空时,会抛出NoSuchElementException异常

b)         

 

3)         Vector

  1. 特点

a)         内部使用可变数组实现

b)        线程安全的

  1. 特有方法

a)         添加

  1. void addElement(E e)
  2. void insertElementAt(E obj,int index)

 

b)        删除

  1. void removeElementAt(int index)
  2. boolean removeElement(Object obj)
  3. void removeAllElements() 删除集合所有元素

c)         修改

  1. void setSize(int newSize):设置内部数组长度,如果newSize大于原数组长度则扩容;如果小于原数组保存元素个数,则将从newSize开始到数组保存最后一个元素都赋值为null
  2. void setElementAt(E obj,int index)

 

d)        获取

  1. int capacity():获取内部维护数组长度
  2. E elementAt(int index):获取指定下标位置的元素
  3. E firstElement() : 返回第一个元素 ,空集合时,抛出NoSuchElementException
  4. E lastElement() :返回最后一个元素,空集合时,抛出NoSuchElementException
  5.  

e)         遍历

  1. Enumeration<T> elements() :返回集合的迭代枚举

f)          拷贝

  1. void copyInto(Object[] anArray):将集合中的元素拷贝到指定的数组中,指定数组长度小于集合中保存的元素的数量,则抛出IndexOutOfBoundsException

g)         缩减数组长度

  1. void trimToSize() : 如果数组中保存元素的大小,小于数组长度,则缩小数组长度与保存元素大小相等

应用:基本已经废弃(由ArrayList替代)

 

(5)      Set集合

1           特点

1)         元素无序(存入和取出的顺序没有顺序)

2)         不允许重复元素,所以最多包含一个null

2           常见方法

1)         Collection

3           实现类

1)         HashSet

  1. 底层结构:维护了一个HashMap,基于hash表实现。
  2. 添加过程:

a)         先通过hashCode()方法的返回值判断

b)        如果hashCode相同,则比较equals方法

  1. 实现去重原理

a)         首先比较添加元素的hashCode(将添加的元素的hashCodehashCode无符号右移16位取异或运算)



/**
* Computes key.hashCode() and spreads (XORs) higher bits of hash
* to lower. Because the table uses power-of-two masking, sets of
* hashes that vary only in bits above the current mask will
* always collide. (Among known examples are sets of Float keys
* holding consecutive whole numbers in small tables.) So we
* apply a transform that spreads the impact of higher bits
* downward. There is a tradeoff between speed, utility, and
* quality of bit-spreading. Because many common sets of hashes
* are already reasonably distributed (so don't benefit from
* spreading), and because we use trees to handle large sets of
* collisions in bins, we just XOR some shifted bits in the
* cheapest possible way to reduce systematic lossage, as well as
* to incorporate impact of the highest bits that would otherwise
* never be used in index calculations because of table bounds.
*/
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

 

b)        如果计算在hash表中的位置相同,则比较equals判断元素是否相等(详情见HashMap

 

 

2)         TreeSet

  1. 底层结构:底层维护了一个TreeMap,基于红黑树实现
  2. 常见方法:
  3. 要求:

a)         要添加集合的元素具备比较性(如果没有在构造器中指定比较器),即元素实现Comparable接口,实现接口内的CompareToT t1T t2)方法

b)        若要添加的元素不具备比较性(没有实现Comparable接口),那么创建TreeSet对象时,必须在构造器中传入一个比较器(Comparator),实现其compareT t2T t2)方法,否则会报类型转换异常。

  1. 去重原理:

a)         自然排序

  1. 根据Comparable方法的compareTo方法的返回值,如果返回0表示相等,则不保存。返回整数排后面,返回负数排前面。

b)        定制排序

  1. 根据Comparator方法的compare方法,返回0表示相等,不保存。
  1. 注意:

a)         当要保存元素即具有比较性,创建TreeSet对象时传入比较器时,则会优先使用比较器。

b)        如果创建TreeSet对象时传入比较器,要保存元素也可以不具备比较性(没有实现Comparable接口)

3)         LinkedHashSet

  1. 底层结构:采用hash表 链表
  2. 特点:

a)         既能够符合HashMap的无序性,也能够按照存入的顺序取出

  1. 常用方法:

a)          同HashSet

  1. 遍历方式:

                                        同HashSEt

                               在这里就不举例了,下面贴出LinkedHashset的源码:


public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {

private static final long serialVersionUID = -2851667679971038690L;


public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}


public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}


public LinkedHashSet() {
super(16, .75f, true);
}

public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}

@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}
}

转载请注明:流年似水 » Java之集合(Collection体系)详解

喜欢 (0)or分享 (0)

Warning: copy(https://cn.gravatar.com/avatar/?s=54&d=%2Fwp-content%2Fthemes%2Fyusi1.0%2Fimg%2Fdefault.png&r=g): failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request in /usr/share/nginx/html/timewentby/wp-content/themes/yusi1.0/functions.php on line 239

Warning: copy(/wp-content/themes/yusi1.0/img/default.png): failed to open stream: No such file or directory in /usr/share/nginx/html/timewentby/wp-content/themes/yusi1.0/functions.php on line 243
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址