一、List集合
List集合:元素有序,可重复的集合,每个元素都有对应的索引。
1. List接口和ListIterator接口
- List接口时Collection接口的子接口。
- List book = new ArrayList(); books.remove(new A());//List会调用该A对象的equals()方法依次与集合元素进行比较,如果equals()方法以某个元素作为参数时返回true,List将会删除该元素。
//按照字符串从短到长排列
books.sort((o1,o2)->((String)o1.length()-(String)o2.length()));
//将每个字符串的长度作为集合的元素
books.replaceAll(ele->((String)ele).length());
- List中提供了listIterator()方法,ListIterator接口继承了Iterator接口,提供了专门操作List的方法,ListIterator接口再Iterator接口基础上增加了如下方法:
boolean hasPrevious():是否有上一个元素
Object previous():返回上一个元素 void
add(Object o):插入一个元素
package TreeCreate;
import java.awt.List;
import java.util.ArrayList;
import java.util.ListIterator;
public class ListIteratorTest {
public static void main(String[] args) {
String[] books = {"Hello","Bonjour"};
ArrayList bookList = new ArrayList();
for(int i = 0; i < books.length; i++) {
bookList.add(books[i]);
}
ListIterator lit = bookList.listIterator();
while(lit.hasNext()) {
System.out.println(lit.next());
lit.add("-----");
}
System.out.println("下面开始反向迭代");
while(lit.hasPrevious()) {
System.out.println(lit.previous());
}
}
}
运行结果:
- ArrayList和Vector实现类
ArrayList和Vector是List类的两个经典实现。它们封装了一个动态的、允许再分配的Object[]数组。ArrayList或Vector对象使用initialCapacity参数来设置该数组的长度,当添加元素超过数组长度时,它们的initialCapacity会自动增加。
ArrayList线程是不安全的,当多个线程访问同一个ArrayList集合时,如果有超过一个线程修改了ArrayList集合,则程序员需要手动保证集合的同步性。
3.固定长度的List
-
asLIst()方法:将一个数组或指定个数的对象转换成一个List集合。这个List集合是Arrays的内部类ArrayList的实例。
-
Arrays.ArrayList是一个固定长度的List集合,只能遍历该集合元素,不可以增加、删除集合中的元素。 List
fixedList = Arrays.asList(“hello”,“Bonjour”);
二、Queue集合
- 1.PriorityQueue、Deque实现类
队列FIFO,Queue接口有一个实现类:PriorityQueue实现类,Queue还有一个Deque接口,Deque是一个“双端队列”,可以同时从两端插入和删除元素,因此它可以当队列和栈使用。
offer()将指定元素加入到队列的尾部。
peek()获取队列头部的元素,
poll()获取队列头部的元素,并删除该元素
PriorityQueue保存队列元素的顺序:元素大小。peek()或poll()方法时,取出的是最小的元素。
2.LinkedList实现类
LinkedList类是(List接口+Deque接口)的实现类,所以可以根据索引来随机访问集合中的元素,内部以链表的形式保存集合中的元素,(随机访问集合元素的性能差,但是插入、删除元素的性能好)还可以把它当成双端队列来使用,可以当成栈或队列来使用。
public class LinkedListTest {
public static void main(String[] args) {
LinkedList books = new LinkedList();
books.offer("Hello");//队列的插入元素,
books.push("Bonjour");//入栈操作
books.offerFirst("Salut");//队列在对头插入元素
for(int i = 0; i < books.size(); i++)
System.out.println(books.get(i));
System.out.println(books);
System.out.println(books.peekFirst());
System.out.println(books.peekLast());
System.out.println(books.pop());
System.out.println(books);
System.out.println(books.pollLast());
System.out.println(books);
}
}
运行结果:
Salut
Bonjour
Hello
[Salut, Bonjour, Hello]
Salut
Hello
Salut
[Bonjour, Hello]
Hello
[Bonjour]
3.各种线性表的性能分析
-
ArrayList基于数组的线性表,LinkedList基于链的线性表。Queue代表了队列,Deque代表了双端队列(队列+栈)。
LinkedList:有List的功能+双端队列+栈的功能。 -
ArrayList 比LinkedList性能好:
ArrayList:基于数组的线性表,因为数组以一块连续内存区来保存所有的数组元素,所以数组在随机访问时性能最好。
LinkedList:基于链表的线性表,在执行插入、删除操作时性能好。
- 关于使用List集合的建议: -
遍历List元素:对于ArrayList和Vector集合,使用随机访问方法(get)来遍历。对于LinkedList集合,采用迭代器(Iterator)遍历。
-
如果经常执行插入、删除操作,使用LinkedList集合。
-
如果有多个线程需要同时访问List集合元素,可考虑使用Collections将集合包装成线程安全的集合。
三、Map(字典、关联数组)集合
1.Map:key-value,一一对应。
key 和 value可以是任何引用类型的数据。元素是无序的。
keySet()方法:返回Map里所有key组成的Set集合。key集和Set集合里元素的存储形式很像,value集和List相似:元素与元素之间可以重复,通过索引来获取元素。
Map中包括一个内部类:Entry,该类封装了一个key-value对。Entry包含了三个方法:
Object getKey()
Object getValue()
Object setValue()
如果添加key-value时,Map中已有key,那么新添加的value会覆盖原来的value.
import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map map = new HashMap();
map.put("hello", 1);
map.put("Bonjour", 2);
map.put("Salut", 3);
System.out.println(map.put("Bonjour", 2222));
System.out.println(map);
System.out.println("是否包含hello:"+map.containsKey("hello"));
System.out.println("是否包含值为3的value:"+map.containsValue(3));
for(Object key:map.keySet()) {
System.out.println(key+"->"+map.get(key));
}
map.remove("hello");
System.out.println(map);
}
}
运行结果:
2
{Salut=3, Bonjour=2222, hello=1}
是否包含hello:true
是否包含值为3的value:true
Salut->3
Bonjour->2222
hello->1
{Salut=3, Bonjour=2222}
2.HashMap和Hashtable的区别
- Hashtable是线程安全的,Hash
Map是线程不安全的,HashMap比Hashtable性能好;但如果多线程访问同一个Map对象时,使用hashtable更好。 - Hashtable不允许使用null作为key和value值;但HashMap可以使用null。 HashMap中最多有一个key = null,但可以有很多value = null.
HashMap和Hashcode判断两个key相等的标准:两个key通过equals()方法比较返回true,hashCode值也相等。
3.LinkedHashMap实现类
使用双向链表来维护key-value对的次序,迭代次序与key-value对的插入顺序一致。因为需要维护元素的插入顺序,所以性能低于HashMap的性能。
4.使用Properties读写属性文件
Properties相当于一个key, value都是String类型的Map。
注意:
Set和Map关系密切,Java源码就是先实现了HashMap、TreeMap
等集合,然后通过包装一个所有的value都是null的Map集合实现了Set集合。
5.各Map的性能分析
- 快---->慢: HashMap > Hashtable > TreeMap > LinkedHashMap
- HashMap:为快速查询设计的(HashMap底层采用数组来存储key-value对)
- 因为TreeMap 底层采用红黑树来管理key-value对,好处是:Tree
Map中的key-value一直处于有序状态,无须进行排序操作。 - LinkedHashMap慢是因为:它需要维护链表来保持Map中key-value的添加顺序
四、同步控制
HashSet, TreeSet, ArrayList, ArrayDeque, LinkedList, HashMap, TreeMap都是线程不安全的。
import java.awt.List;
import java.util.*;
public class SynchronizedTest {
public static void main(String[] args) {
Collection c = Collections.synchronizedCollection(new ArrayList());
List list = (List) Collections.synchronizedList(new ArrayList());
Set s = Collections.synchronizedSet(new HashSet());
Map m = Collections.synchronizedMap(new HashMap());
}
}