建议使用目录功能来查看内容。
Set(集)
特点:Set集合存储元素的特性是无序且不可重复的。还有Set是基于map实现的,详情可看Set实现类的源码。
Set集合的大部分方法和Collection接口差不多,只有TreeSet新增了较多方法。
主要实现类:
- HashSet:元素是无序的,因为底层操作是HashMap来完成的,所以没有重复值,但可以存入null。
- LinkedHashSet:是HashSet子类,使用链表维护元素次序,元素按照插入次序来排序,其他和HashSet没区别。
- TreeSet:会对元素进行排序,元素都需要实现Comparator接口(Java常用类都已实现),如果是添加自定义的类作为元素,需要制定排序规则。
- TreeSet如果加入不同元素,则元素之间无法比较,所以TreeSet的元素都是同一类型。
- TreeSet增加了许多方法,有获取头尾元素截取一部分元素和使用降序来遍历元素的迭代器,这里不详述。
HashSet的简单示例
HashSet hs = new HashSet();
hs.add("A");
hs.add("潇湘");
hs.add(2);
hs.add(2);
hs.add(new Date());
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("元素个数:" + hs.size());
System.out.println("移除元素:" + hs.remove("A"));
hs.clear();//清除所有元素
System.out.println("元素个数:" + hs.size());
- 实例说明:HashSet是Set集合的典型实现,我们要获取Set集合元素除了使用迭代器,还可以使用加强for循环。也可以将集合转成数组。
LinkedHashSet的简单示例
LinkedHashSet hs = new LinkedHashSet();
hs.add("A");
hs.add("潇湘");
hs.add(2);
hs.add(new Date());
//使用for-each来遍历元素
for(Object lhs : hs) {
System.out.println(lhs);
}
- 实例说明:LinkedHashSet和HashSet差不多,不同的就是该类是按照元素的插入次序来排序的。遍历元素可以查看效果。
TreeSet的简单示例
TreeSet ts = new TreeSet();
ts.add(10);
ts.add(10);
ts.add(30);
ts.add(-50);
System.out.println(ts);
- 实例说明:使用TreeSet添加多个数值,打印结果是显示有序的。但TreeSet的排序规则不是按照插入次序,而是按照已实现的自然排序来排序。也可以自定义排序。
TreeSet加入不同类型元素的简单示例
public class TreeSetTest {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add("A");
ts.add("B");
ts.add("C");
System.out.println(ts.toString());
ts.add(1);
System.out.println(ts); //ClassCastException
}
}
- 实例说明:TreeSet添加不同类型元素,会导致元素之间无法比较,那TreeSet就无法保证排序状态,引发异常。如果使用泛型可以避免数据不一致。
TreeSet新增方法简单示例
TreeSet ts = new TreeSet();
ts.add(10);
ts.add(20);
ts.add(-50);
System.out.println(ts);
System.out.println("--------------------");
Iterator it = ts.descendingIterator();//降序迭代器,从大到小
while(it.hasNext()) {
System.out.print(it.next() + " ");
}
//获取>=给定元素的最小元素
System.out.println("ceiling:" + ts.ceiling(18));
System.out.println(ts.first());//第一个元素
System.out.println(ts.last());//最后一个元素
System.out.println(ts.pollFirst());//获取第一位元素,然后移除该元素
System.out.println(ts.pollLast());//获取最后的元素,然后移除该元素
}
特点:List集合的元素是有序的且可重复。每个元素都有对应的索引,默认按照添加的顺序设置索引。
主要实现类:
- ArrayList:底层是一个可变数组,默认容量10,可以指定初始容量。主要应用在查找和更改。
- LinkedList:底层由链表来维护。主要应用在添加和删除
List的独有迭代器:ListIterator
- ListIterator对Iterator进行了扩展,新增向前迭代、增加元素和修改元素的方法:hasPrevious() 、previous()、add()、set()
List类根据索引新增的方法:
新增的都是根据索引来进行增删改查的方法。
List方法 | 作用描述 |
---|---|
E add(int index, Object obj) | 把指定元素添加到指定索引值对应的元素 。 |
E remove(int index) | 移除指定索引值对应的元素。 |
E set(int index, E element) | 用指定元素替换指定索引值对应的元素。 |
E get(int index) | 返回指定索引值的元素。 |
int indexOf(Object o) | 返回该集合中指定元素第一次出现的索引值;不包含该元素,则返回 -1。 |
int lastIndexOf(Object o) | 返回该集合中指定元素最后一次出现的索引值;不包含该元素,则返回 -1。 |
ListIterator<E> listIterator() | 返回此列表元素的列表迭代器(按适当顺序)。 |
ListIterator<E> listIterator(int index) | 返回列表中元素的列表迭代器(按适当顺序),从指定位置开始。 |
List<E> subList(int fromIndex, int toIndex) | 返回指定的 fromIndex(包括 )和 toIndex(不包括)之间的子集合。 |
ArrayList和LinkedList的简单示例
ArrayList与LinkedList的主要差别在底层实现方式不一样,但方法差不多。所以这里只使用ArrayList来演示索引方法
ArrayList al = new ArrayList(15);//指定初始长度,默认是10
al.add("A");
al.add("B");
al.add(10);
al.add(20);
System.out.println("移除之前:" + al);
al.remove(1); //移除索引值1的对应元素
System.out.println("移除之后:" + al);
//获取此时索引值1的对应元素
System.out.println("索引1处的元素:" + al.get(1));
//在索引值1处添加元素
al.add(1,"add");
System.out.println("使用add()在索引1处添加元素:" + al);
//修改索引1值的对应元素
al.set(1, "使用set()");
System.out.println("使用set()修改元素:" + al);
System.out.println(al.indexOf("使用set()"));//获取元素"使用set()"的索引值
for(int i = 0; i < al.size(); i++) {
System.out.println(i + "-->" + al.get(i));
}
上面代码中要注意区别add()和set(),add()添加元素至指定索引处,原该索引处的数据依次向后移动,相当于插入元素。set()是对指定索引处的元素进行修改,会覆盖元素。
List特有迭代器—ListIterator的简单示例
ArrayList al = new ArrayList(15);
al.add("A");
al.add("B");
al.add(10);
al.add(20);
System.out.println("----使用ListIterator-----");
ListIterator lis = al.listIterator();
while(lis.hasNext()) {
System.out.println(lis.next());
}
System.out.println("--------反向迭代---------");
while(lis.hasPrevious()) {
System.out.println(lis.previous());
}
需要注意:使用hasPrevious()进行反向迭代的前提是先使用一次正向迭代,不然无法迭代元素。
Queue(队列)
Queue集合封装了栈、队列和双端队列数据结构,Queue集合类不支持随机访问元素。
- 队列特点:先进先出(FLFO)容器。
- 栈的特点:先进后出(FILO)容器。
- 双端队列特点:拥有栈和队列的特性,可以对队列头部和尾部进行删除和插入操作。
主要实现类:
- ArrayDeque:基于数组实现的双端队列。
- PriorityQueue:使用自然排序或定制排序来对元素进行排序,但排序是堆排序。不能插入null。
- LinkedList:实现了List、Queue、Deque接口,既能使用索引,又能模拟双端队列。功能很强大,这里仅做了解。
- ArrayDeque和LinkedList可以作为双端队列,具有FIFO和FILO特性。
双端队列的常用方法
因为实现了Deque和Queue接口,方法众多,但方法中带Frist都是用于操作队头,Last则是操作队尾。建议使用这种方法,简单明了。
boolean add(E e)_____________________________将指定元素插入末尾
void addFirst(E e)__________________________将指定元素插入开头
void addLast(E e)___________________________将指定元素插入末尾
boolean offer(E e)__________________________将指定元素插入末尾
boolean offerFirst(E e)_____________________将指定元素插入末尾
boolean offerLast(E e)______________________将指定元素插入末尾
E getFirst()________________________________获取第一个元素,但不移除
E getLast()_________________________________获取最后一个元素,但不移除
E peekFirst()_______________________________获取双端队列第一个元素,但不移除。
E peekLast()________________________________获取双端队列最后一个元素,但不移除。
E pollFirst()_______________________________获取并移除第一个元素
E pollLast()________________________________获取并移除最后一个元素
E removeFirst()_____________________________获取并移除第一个元素
E removeLast()______________________________获取并移除最后一个元素
E pop()_____________________________________模拟栈弹出一个元素,弹栈
void push(E e)______________________________将元素推入栈中,压栈
boolean removeFirstOccurrence(Object o)_____移除第一次出现的指定元素(当从头部到尾部遍历双端队列时)
boolean removeLastOccurrence(Object o)______移除最后一次出现的指定元素(当从头部到尾部遍历双端队列时)
ArrayDeque的简单示例
ArrayDeque ad = new ArrayDeque();
ad.add("A");
ad.add("阴");
ad.add("阳");
ad.add(100);
System.out.println(ad);
//获取队头元素和队尾
System.out.println("队头元素:" + ad.getFirst());
System.out.println("队尾元素:" + ad.getLast());
//把元素插入队尾
ad.offer("offer加入队尾");
ad.add("add加入队尾");
System.out.println(ad);
//移除队列头部元素
ad.removeFirst();
//移除队列最后的元素
ad.removeLast();
System.out.println("移除队头和队尾元素" + ad);
PriorityQueue的简单示例
该类是一个标准队列(FIFO),使用的是堆排序。这意味我们直接打印PriorityQueue对象时,结果可能会不符合我们的要求,它不是会自动排序吗??代码实例如下: PriorityQueue<Integer> al = new PriorityQueue<>();
al.add(18);
al.add(30);
al.add(-5);
al.add(9);
al.add(15);
System.out.println(al.toString()); //[-5, 9, 18, 30, 15]
- 实例说明:因为堆排序只会保证第一个元素也就是根节点的元素是当前优先队列里最小的,只要元素变化都会导致堆重排,例如使用了offer()添加元素或者poll()获取头部元素。
- 解决方式:使用for循环来遍历元素。注意:加强for循环和迭代器遍历元素都会出现不符合预期的结果。
int len = al.size(); //保证遍历次数是原本的元素数量
for(int i=0; i < len; i++) {
System.out.print(al.poll() + " "); //获取元素之后就会移除该元素。
}