/**
@Author: Ly
@Date: 2020-08-13 08:46
*/
public class ListFeatures {
public static void main(String[] args) {
List li = new ArrayList();
for(int i = 0; i < 10; i++)
li.add(i);
Integer h = 10;
li.add(h); //将指定的元素追加到此列表的末尾
li.add(1,0); //将指定的元素插入此列表中的指定位置
li.remove(0); //删除该列表中指定位置的元素
System.out.println(li);
System.out.println(li+"集合中含有:h "+li.contains(h));
li.set(0,10); //用指定的元素替换此列表中指定位置的元素
Integer p = li.get(0);//返回此列表中指定位置的元素
System.out.println(“数字”+p + “第一次出现位置的索引为:” + li.indexOf§); //打印此列表中指定元素的第一次出现的索引
li.remove§; //删除指定元素的第一次出现
System.out.println(li);
List sub = li.subList(1, 4);//用列表中第1到第4个(不包含第4个)元素创建新的集合
Boolean bl=li.containsAll(sub); //看列表是否包含指定集合的所有元素
System.out.println(“集合li中”+ (bl?“含有”:“不含有”) +“sub中的所有元素”);
List copy = new ArrayList(li);
copy.removeAll(sub); //从此列表中删除包含在指定集合中的所有元素
System.out.println(“copy集合:”+copy);
if(copy.size() > 1) //如果列表中的元素数大于1
copy.addAll(2, sub);//将指定集合中的所有元素插入到此列表中的指定位置
System.out.println(“copy集合:”+copy);
Object[] objects = li.toArray();//以正确的顺序返回一个包含此列表中所有元素的数组
for(Object o:objects){
System.out.print(o+", ");
}
System.out.println(li.isEmpty());//如果此列表不包含元素,则返回 true
li.clear();//从此列表中删除所有元素
System.out.println(li+":"+ li.isEmpty());
}
}
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]集合中含有: h true
数字10第一次出现位置的索引为:0
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
集合li中含有sub中的所有元素
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
copy集合:[1, 5, 6, 7, 8, 9, 10]
copy集合:[1, 5, 2, 3, 4, 6, 7, 8, 9, 10]
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, false
[]:true
2. LinkedList: 它通过代价较低的在List中间插入和删除操作,提供了优化的顺序访问。LinkedList在随机访问方面相对比较慢,但是它的特性集较ArrayList更大。
例:
/**
@Author: Ly
@Date: 2020-08-13 12:24
*/
public class LinkedListFeatures {
public static void main(String[] args) {
LinkedList list = new LinkedList();
for (int i = 1; i < 10; i++) {
list.add(i);
}
System.out.print(list.getFirst()+" "); //返回此列表中的第一个元素,为空时抛出异常
System.out.print(list.element()+" "); //检索但不删除此列表的头,为空时抛出异常
System.out.print(list.peek()+" "); //检索但不删除此列表的头,为空时返回null
System.out.print(list.removeFirst()+" "); //检索并删除此列表的头,为空时抛出异常
System.out.print(list.remove()+" "); //检索并删除此列表的头,为空时抛出异常
System.out.print(list.poll()+" "); //检索并删除此列表的头,为空时返回null
System.out.println();
System.out.println(list);
list.addFirst(0); //在该列表开头插入指定的元素
list.offer(10); //将指定的元素添加为此列表的末尾
list.add(11); //将指定的元素追加到此列表的末尾
list.addLast(12); //将指定的元素追加到此列表的末尾
list.removeLast(); //从此列表中删除并返回最后一个元素。
System.out.println(list);
}
}
Output:
1 1 1 1 2 3
[4, 5, 6, 7, 8, 9]
[0, 4, 5, 6, 7, 8, 9, 10, 11]
LinkedList也像ArrayList一样实现了基本的List接口,但是它执行某些操作时比ArrayList更高效,但是随机访问操作方面要差一些。LinkedList中添加了可以使其用作栈、队列或双端队列的方法。
3. Stack:
“栈”通常是指“后进先出(LIFO)”的容器
,有时也称为叠加栈,LinkedList具有能够直接实现栈的所有功能的方法,因此可以直接将LinkedList作为栈使用。
/*
通过使用泛型,引入了在栈的类定义中最简单的可行示例。
类名之后的告诉编译器这将是一个参数化类型(在类被使用时将会被实际类型替换的参数)。
Stack使用LinkedList实现的,而LinkedList也被告知它将持有T类型对象;
*/
class Stack {
private LinkedList storage=new LinkedList();
public void push(T v){storage.addFirst(v);}
public T peek() {return storage.getFirst();}
public T pop () {return storage.removeFirst();}
public boolean empty () {return storage.isEmpty(); }
public String toString (){return storage.toString();}
}
public class StackTest{
public static void main(String[] args) {
Stack stack = new Stack ();
for (String s : “One Two Three”.split(" "))
stack.push(s);
while (!stack.empty())
System.out.print(stack.pop()+" ");
}
}
Output:
Three Two One
2.2 Set
Set不保存重复的元素;
Set中最常用的是测试归属性,可以很容易地询问某个对象是否在某个Set中。正因如此,查找成了Set中最重要的操作,因此通常会选择一个HashSet的实现,它专门对快速查找进行了优化。(Hash查找最快。)
/**
@Author: Ly
@Date: 2020-08-14 19:27
*/
public class SetOfInteger {
public static void main(String[] args) {
Random rand=new Random(47);
Set intSet =new HashSet();
//如果想对结果排序,使用TreeSet来替代HashSet,不过在测试HashSet时你会发现打印出来的也是排序好的结果
//SortedSet intSet =new TreeSet();
for (int i = 0; i<10000 ; i++){
intSet.add(rand.nextInt(30));
};
System.out.println(intSet);
//使用contains()测试Set的归属性
System.out.println(intSet.contains(5));
System.out.println(intSet.contains(30));
}
}
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
true
false
TreeSet将元素存储在红-黑数据结构中,而HashSet使用的是散列函数。LinkedHashSet因为查询速度的原因也使用了散列,但是看起来它使用了链表来维护元素的插入顺序。
2.3 Map
将对象映射到其他对象的能力是一种解决编程问题的杀手锏;
考虑一个程序,它将用来检查Java的Random类的随机性。理想情况下,Random可以产生理想的数字分布,但要想测试它,则需要生成大量的随机数,并对落入各种不同范围的数字进行计数。Map可以很容易地解决该问题。在这个问题中,键是由Random产生的数字,值是该数字出现的次数:
/**
@Author: Ly
@Date: 2020-08-14 20:38
*/
public class Statistics {
public static void main(String[] args) {
Random rand=new Random(47);
Map<Integer,Integer> m=
new HashMap<Integer,Integer>();
for(int i= 0; i <10000 ;i++){
int r=rand.nextInt(20);
Integer freq = m.get®;
m.put(r,freq==null ? 1 : freq+1);
}
System.out.println(m);
//containsKey()和containsValue()来测试Map,以便查看它是否包含某个键或某个值:
System.out.println(m.containsKey(10));
System.out.println(m.containsValue(500));
}
}
Output:
{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, 7=471, 8=468, 9=549,
10=513, 11=531, 12=521, 13=506, 14=477, 15=497, 16=533, 17=509, 18=478, 19=464}
true
false
Map与数组和其他的Collection一样,可以很容易地扩展到多维,而我们只需将其值设置为Map(这些Map的值可以是其他容器,甚至是其他Map)。因此,能够很容易地将容器组合起来从而快速地生成强大的数据结构。
class Person{
private String name;
Person(String name){
this.name=name;
}
@Override
public String toString() {
return name;
}
}
public class MapOfList {
public static Map<Person , List>
petPeople = new HashMap<Person,List>();
static{
petPeople.put(new Person(“Dawn”),
Arrays.asList (“Cymric_Molly”,“Mutt_Spot”));
petPeople.put(new Person(“Kate”),
Arrays.asList (“Cat_Shackleton”, “Cat_Elsie”, “Dog_Margret”));
petPeople.put(new Person(“Marilyn”),
Arrays.asList(“Pug_Louie”, “Cat_Negro”, “Cat_Pinkola”));
petPeople.put (new Person(“Luke”),
Arrays.asList(“Rat_Fuzzy”, “Rat_Fizzy”));
petPeople.put(new Person (“Isaac”),
Arrays.asList(“Rat_Freckly”));
}
public static void main(String[] args) {
System.out.println("People: "+ petPeople.keySet());
System.out.println("Pets: "+ petPeople.values());
for(Person person : petPeople.keySet()){
System.out.print(person + " has : ");
for (String str : petPeople.get(person))
System.out.print(" "+str);
System.out.println();
}
}
}
Output:
Luke has : Rat_Fuzzy Rat_Fizzy
Marilyn has : Pug_Louie Cat_Negro Cat_Pinkola
Isaac has : Rat_Freckly
Dawn has : Cymric_Molly Mutt_Spot
Kate has : Cat_Shackleton Cat_Elsie Dog_Margret
Map是一种将对象(而非数字)与对象相关联的设计。HashMap设计用来快速访问;而TreeMap保持“键”始终处于排序状态,所以没有HashMap快。LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问能力。
2.4 Queue
队列是一个典型的先进先出(FIFO)的容器。
即从容器的一端放入事物,从另一端取出,并且将事物放入容器的顺序与取出的顺序是相同的。队列常被当作一种可靠的将对象从程序的某个区域传输到另一个区域的途径。队列在并发编程中特别重要。
LinkedList提供了方法以支持队列的行为,并且它实现了Queue接口,因此LinkedList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue,下面的示例使用了在Queue接口中与Queue相关的方法:
/**
@Author: Ly
@Date: 2020-08-14 21:00
*/
public class QueueDemo {
public static void printQ(Queue queue) {
//peek(),element(): 在不移除的情况下返回队头
//peek():在队列为空时返回null
//element():在队列为空时抛出NoSuchElementException异常
while(queue.peek()!= null)
System.out.print(queue.remove()+" ");
System.out.println();
}
public static void main(String[] args) {
Queue queue = new LinkedList();
Random rand = new Random(47);
for(int i=0;i<10;i++)
//offer(): 在允许的情况下,将一个元素插入到队尾,或者返回false
queue.offer(rand.nextInt(i+10));
printQ(queue);
Queue qc= new LinkedList();
for(char c :“Brontosaurus”.toCharArray())
qc.offer©;
System.out.println(qc);
}
}
Output:
3 10 7 0 10 3 6 7 4 5
[B, r, o, n, t, o, s, a, u, r, u, s]
Queue接口窄化了对LinkedList的方法的访问权限,以使得只有恰当的方法才可以使用,因此,你能够访问的LinkedList的方法会变少。注意:与Queue相关的方法提供了完整而独立的功能。即,对于Queue所继承的Collection,在不需要使用它的任何方法的情况下,就可以拥有一个可用的Queue。
PriorityQueue:
先进先出描述了最典型的队列规则。队列规则是指在给定一组队列中的元素的情况下,确定下一个弹出队列的元素的规则。
先进先出声明的是下一个元素应该是等待时间最长的元素。
优先级队列声明下一个弹出元素是最需要的元素(具有最高的优先级)。如果构建了一个消息系统,某些消息比其他消息更重要,因而应该更快地得到处理,那么它们何时得到处理就与它们何时到达无关。
/**
@Author: Ly
@Date: 2020-08-14 21:46
*/
public class PriorityQueueDemo {
public static void main(String[] args) {
PriorityQueue priorityQueue= new PriorityQueue ();
Random rand= new Random (47);
for(int i=0;i<10; i++)
priorityQueue.offer(rand.nextInt(i+10));
QueueDemo.printQ(priorityQueue);
List ints = Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25);
priorityQueue=new PriorityQueue(ints);
QueueDemo.printQ(priorityQueue);
priorityQueue=new PriorityQueue(ints.size(), Collections.reverseOrder());
priorityQueue.addAll(ints);
QueueDemo.printQ(priorityQueue);
String fact = " EDUCATION SHOULD ESCHEW OBFUSCATION ";
List strings =Arrays.asList(fact.split(" "));
PriorityQueue stringPQ =new PriorityQueue(strings);
QueueDemo.printQ(stringPQ);
stringPQ= new PriorityQueue(
strings.size(),Collections.reverseOrder());
stringPQ.addAll(strings);
QueueDemo.printQ(stringPQ);
Set charSet =new HashSet();
for(char c : fact.toCharArray())
charSet.add©;
PriorityQueue characterPQ= new PriorityQueue(charSet);
QueueDemo.printQ(characterPQ);
}
}
Output:
0 1 1 1 1 1 3 5 8 14
1 1 2 3 3 9 9 14 14 18 18 20 21 22 23 25 25
25 25 23 22 21 20 18 18 14 14 9 9 3 3 2 1 1
EDUCATION ESCHEW OBFUSCATION SHOULD
SHOULD OBFUSCATION ESCHEW EDUCATION
A B C D E F H I L N O S T U W
在这里,重复是允许的,最小的值拥有最高的优先级(如果是String,空格也算作值,并且优先级比字母的高)。
例子展示了如何通过自己的Comparator对象来改变排序,这里调用Collection.reverseorder()来对原来的顺序进行倒序排列。最后一部分添加了一个HashSet来消除重复的Character;
迭代器
3.1 迭代器:Iterator
迭代器是一个帮助我们做集合遍历的工具。
java中提供了很多种集合,它们在存储元素时,采用的存储方式不同。这时当我们将同样的代码用于不同的集合时就会出现问题。而此时引入迭代器便可以解决这个问题,通过使用迭代器,我们可以通过一种通用的获取方式来取出集合中的元素。
迭代器是一个对象,它的工作是遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层的结构。此外迭代器通常被称为轻量级对象:创建它的代价小。因此,经常可以见到对迭代器有些奇怪的限制;例如,Java的Iterator只能单向移动,这个Iterator只能用来:
1.使用方法iterator()要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素。
2.使用next()获得序列中的下一个元素。
3.使用hasNext()检查序列中是否还要元素。
4.使用remove()将迭代器新近返回的元素删除。
/**
@Author: Ly
@Date: 2020-08-13 11:20
*/
public class SimpleIteration {
public static void main(String[] args) {
List list=new ArrayList();
for (int i = 1; i < 10; i++) {
list.add(i);
}
Iterator it=list.iterator();
while(it.hasNext()){
Integer i=it.next();
System.out.print(i+" ");
}
System.out.println();
it=list.iterator();
for (int i = 0; i < 6; i++) {
it.next();
it.remove();
}
System.out.println(list);
}
}
3.2 ListIterator:
ListIterator是一个更加强大的Iterator的子类型,它只能用于各种List类的访问。
Iterator只能向前移动,而ListIterator可以双向移动。其可以产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引,并通过相应方法进行操作:
set()方法: 替换它访问过得最后一个元素。
ListIterator()方法: 产生一个指向List开始处的ListIterator。
listIterator(n)方法: 创建一个一开始就指向列表索引为n的元素处的ListIterator。
例:
/**