Java中List和Set接口

时间:2022-09-02 16:16:41

1.Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。
其继承了java迭代接口Iterable。
源码:

... * @see     AbstractCollection
* @since 1.2
*/

public interface Collection<E> extends Iterable<E> {
// Query Operations

1.1 List接口

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
源码:

...<br> * @see AbstractList
* @see AbstractSequentialList
* @since 1.2
*/

public interface List<E> extends Collection<E> {
// Query Operations

/**
* Returns the number of elements in this list. If this list contains
* more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
<br> ...

和Set不同,List允许有相同的元素。
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

1.1.1ArrayList类

源码定义:
Java中List和Set接口
ArrayList数组线性表的特点为:类似数组的形式进行存储,因此它的随机访问速度极快。
ArrayList数组线性表的缺点为:不适合于在线性表中间需要频繁进行插入和删除操作。因为每次插入和删除都需要移动数组中的元素。

ArrayList就是基于数组的线性表,只不过长度可以动态改变而已。
a.在JDK1.7中,如果通过无参构造的话,初始数组容量为0,当真正对数组进行添加时,才真正分配容量。

Java中List和Set接口
b.增容是扩大1.5倍,用右移运算符。
Java中List和Set接口
c.ArrayList是线程不安全的
如果一定在多线程使用List的,您可以使用Vector,因为Vector和ArrayList基本一致,区别在于Vector中的绝大部分方法都使用了同步关键字修饰,这样在多线程的情况下不会出现并发错误哦,还有就是它们的扩容方案不同,Vector是允许设置默认的增长长度,Vector的默认扩容方式为原来的2倍。

切记Vector是ArrayList的多线程的一个替代品。
d.ArrayList遍历

     List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("lcccc");
//第一种遍历方法使用foreach遍历List
/*
for (String str : list) {
System.out.println(str);
}

for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
*/

//第二种遍历,把链表变为数组相关的内容进行遍历
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //这里也可以改写为foreach(String str:strArray)这种形式
{
System.out.println(strArray[i]);
}

//第三种遍历 使用迭代器进行相关遍历

Iterator<String> ite=list.iterator();
while(ite.hasNext())
{
System.out.println(ite.next());
}

1.1.2LinkedList

LinkedList的链式线性表的特点为: 适合于在链表中间需要频繁进行插入和删除操作。
LinkedList的链式线性表的缺点为: 随机访问速度较慢。查找一个元素需要从头开始一个一个的找。
a. 类定义源码:
Java中List和Set接口
LinkedList继承自AbstractSequenceList、实现了List及Deque接口。其实AbstractSequenceList已经实现了List接口,这里标注出List只是更加清晰而已。AbstractSequenceList提供了List接口骨干性的实现以减少实现List接口的复杂度。Deque接口定义了双端队列的操作。
b. 声明的成员变量
Java中List和Set接口
size是存储元素的个数first和last分别表示首尾节点,为Node类型。
c. Node源码
Java中List和Set接口
定义了存储的元素、前一个元素、后一个元素,这就是双向链表的节点的定义,每个节点只知道自己的前一个节点和后一个节点。
d. 构造方法

public LinkedList() {
header.next = header.previous = header;
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}

LinkedList不是线程安全的。
e. 遍历LinkedList

        List<String> list=new LinkedList<String>();
list.add("Hello");
list.add("World");
list.add("lc");
//LinkedList遍历的第一种方式使用数组的方式
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(String str:strArray)
{
System.out.println(str);
}
//LinkedList遍历的第二种方式
for(String str:list)
{
System.out.println(str);
}

1.2 Set接口

Set接口是Collection接口的子接口了吧。

Set接口区别于List接口的特点在于:

Set中的元素实现了不重复,有点象集合的概念,无序,不允许有重复的元素,最多允许有一个null元素对象。
定义:
Java中List和Set接口

需要注意的是:虽然Set中元素没有顺序,但是元素在set中的位置是有由该元素的HashCode决定的,其具体位置其实是固定的。
举一个例子:对象A和对象B,本来是不同的两个对象,正常情况下它们是能够放入到Set里面的,但是
如果对象A和B的都重写了hashcode和equals方法,并且重写后的hashcode和equals方法是相同的话。那么A和B是不能同时放入到Set集合中去的,也就是Set集合中的去重和hashcode与equals方法直接相关。
Set接口的常见实现类有HashSet,LinedHashSet和TreeSet这三个

1.2.1 HashSet

HashSet是Set接口的最常见的实现类了。其底层是基于Hash算法进行存储相关元素的。
定义:
Java中List和Set接口
HashSet的底层就是基于HashMap来实现的。HashMap中的key是不允许重复的。HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个private static final Object PRESENT = new Object();。
Java中List和Set接口

注意:

a. HashSet中存放null值HashSet中时允许出入null值的,但是在HashSet中仅仅能够存入一个null值哦。
b.HashSet中存储元素的位置是固定的HashSet中存储的元素的是无序的,这个没什么好说的,但是由于HashSet底层是基于Hash算法实现的,使用了hashcode, 所以HashSet中相应的元素的位置是固定的哦。

 Set set = new HashSet();
set.add("Hello");
set.add("world");
set.add("Hello");
//遍历集合的第一种方法,使用数组的方法
String[] strArray=new String[set.size()];
strArray=set.toArray(strArray);
for(String str:strArray)//此处也可以使用for(int i=0;i<strArray.length;i++)
{
System.out.println(str);
}
//遍历集合的第二中方法,使用set集合直接遍历
for(String str:set)
{
System.out.println(str);
}

//遍历集合的第三种方法,使用iterator迭代器的方法
Iterator<String> iterator=set.iterator();
while(iterator.hasNext())
{
System.out.println(iterator.next());
}

1.2.2 LinkedHashSet

(待填充)

1.2.3 TreeSet

TreeSet是一种排序二叉树。存入Set集合中的值,会按照值的大小进行相关的排序操作。底层算法是基于红黑树来实现的。
TreeSet和HashSet的主要区别在于TreeSet中的元素会按照相关的值进行排序
HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key。