0%

常用的集合类笔记

摘要:
介绍常用的set、Map、List

概述

  • List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口
  • Set下有HashSet,LinkedHashSet,TreeSet
  • List下有ArrayList,Vector,LinkedList
  • Map下有Hashtable,LinkedHashMap,HashMap,TreeMap

A、总结

1.List 有序,可重复:

  • ArrayList
    优点: 底层数据结构是数组,查询快,增删慢。
    缺点: 线程不安全,效率高
  • Vector
    优点: 底层数据结构是数组,查询快,增删慢。
    缺点: 线程安全,效率低
  • LinkedList
    优点: 底层数据结构是链表,查询慢,增删快。
    缺点: 线程不安全,效率高

2.Set 无序,唯一:

  • HashSet
    底层数据结构是哈希表。(无序,唯一)
    如何来保证元素唯一性?

1.依赖两个方法:hashCode()和equals()

  • LinkedHashSet
    底层数据结构是链表和哈希表。(FIFO插入有序,唯一)

1.由链表保证元素有序
2.由哈希表保证元素唯一

  • TreeSet
    底层数据结构是红黑树。(唯一,有序)
    1 如何保证元素排序的呢?
    自然排序
    比较器排序
    2如何保证元素唯一性的呢?
    根据比较的返回值是否是0来决定

Tips:
Set中元素唯一,list不唯一;
list中vector安全,ArrayList和LinkedList不安全;
ArrayList查询方便,因为底层是数组,LinkedList增删方便,底层是链表结构

3.Map:

Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。

Map的Tips:

1.TreeMap是有序的,HashMap和HashTable是无序的。
2.Hashtable是线程安全的,HashMap不是线程安全的。
3.Hashtable不允许null值,HashMap允许null值(key和value都允许)
4.HashMap效率较高,Hashtable效率较低。

B、几种常用集合的函数使用

1. List

1.1ArrayList

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//初始化
List<String> person=new ArrayList<>();或者
ArrayList<String> list = new ArrayList<String>();
//添加
person.add(index,element);
person.add("jackie"); //索引为0 //.add(e)
person.add("peter"); //索引为1
person.add("annie"); //索引为2
person.add("martin"); //索引为3
//删除元素
person.remove(3); //.remove(index)
person.remove("marry"); //.remove(Object o)
//获取
person.get(1); //.get(index)
//获取列表的长度num
int num=person.size();
//list中是否包含某个元素
person.contains(Object o);//返回值为boolean类型数据
//list中根据索引将元素数值改变(替换)
person.set(index,element);
person.set(0,"zhangsan");
//查看(判断)元素的索引;因为可能存在多个相同的元素值,list允许元素相同
person.indexOf("zhangsan");//从第一个索引向后一次equals()方法获取元素值相同的索引
person.lastIndexOf("zhangsan")//从最后一个索引向前遍历list获取相同元素值得索引
//由索引截取list
List<String> newPerson=new ArrayList<>();
newPerson=person.subList(fromIndex, toIndex);//子表中不包含toIndex
//list间赋值
List<String> person2=new ArrayList<>();
person2.add("12");
person2.add("13");
person.addAll(person2);//将列表person2加至person末尾
person.addAll(0, person2);//将列表person2加至person索引指示的位置
//与上同理,list之间是否包含
person.containsAll(person2);
//对比两个list中的所有元素
person.equals(newPerson);//返回值为boolean类型
//判断list是否为空
person.isEmpty();//返回值为boolean类型
//将集合转换为字符串
String liString="";
liString=person.toString()
//将List转换成数组
person.toArray();
//获取迭代值对象
ListIterator lit = person.listIterator();
while(lit.hasNext())
{
System.out.println(lit.next());
//向迭代对象中添加分隔符字符串
lit.add("-----分隔符-----");
}
System.out.println("=====下面开始反向迭代=====");
while(lit.hasPrevious())
{
System.out.println(lit.previous());
}

1.2 LinkedList

优点

  • 有序、可以向前面和向后添加 、中间插入也很方便 、可以用实现简单队列模式(removeFirst() 处理队列中的任务,add(); 向队列中排队)

缺点:

  • 消耗内存有点大、定位删除和定位查找 都是比较慢、检索能力差
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
//初始化
List<String> person=new LinkedList<>();
//增元素
person.add(E e); 在链表后添加一个元素
person.addFirst(E e); 在链表头部插入一个元素;
person.addLast(E e);在链表尾部添加一个元素;
person.push(E e);与addFirst方法一致
person.offer(E e);在链表尾部插入一个元素 person.add(int index, E element);在指定位置插入一个元素。
person.offerFirst(E e);JDK1.6版本之后,在头部添加; person.offerLast(E e);JDK1.6版本之后,在尾部添加;
//删
person.remove() :移除链表中第一个元素; 通用方法
person.remove(E e):移除指定元素; 通用方法
person.removeFirst(E e):删除头,获取元素并删除; 特有方法
person.removeLast(E e):删除尾; 特有方法
person.pollFirst():删除头; 特有方法
person.pollLast():删除尾; 特有方法
person.pop():和removeFirst方法一致,删除头。
person.poll():查询并移除第一个元素 特有方法
//查
person.get(int index):按照下标获取元素; 通用方法
person.getFirst():获取第一个元素; 特有方法
person.getLast():获取最后一个元素; 特有方法
person.peek():获取第一个元素,但是不移除; 特有方法
person.peekFirst():获取第一个元素,但是不移除;
person.peekLast():获取最后一个元素,但是不移除;
person.pollFirst():查询并删除头; 特有方法
person.pollLast():删除尾; 特有方法
person.poll():查询并移除第一个元素 特有方法

2. Set

2.1 HashSet

HashSet是set接口的实现类,储存的是无序,唯一的对象。
由于是无序的所以每组数据都没有索引,凡是需要通过索引来进行操作的方法都没有。
不能使用普通for循环来进行遍历,只有加强型for和迭代器两种遍历方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//初始化
HashSet<String> set=new HashSet<String>();
//添加元素,添加成功返回true,否则返回false
set.add(Object obj);
set.add("tom");
set.add("bob");
//返回Set集合中的元素个数
set.size();
//验证非空
set.isEmpty();//返回Boolean值
//移除此Set中的所有元素
set.clear();
//是否包含某元素
set.contains("bob");
//删除集合中的元素,删除成功返回true,否则返回false
set.remove("bob");
//返回在此Set中的元素上进行迭代的迭代器
Iterator<String> iterator=set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
//遍历集合是无序的,可能每次结果不相同

2.2 TreeSet

TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。

3. Map

3.1 HashMap

根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap最多只允许一条记录的键为null,允许多条记录的值为null。

HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//初始化
HashMap<String, String> map = new HashMap<>();
//添加键值对
map.put("zhang", "31");//存放键值对
//通过键拿值
map.get("zhang");
//判断是否包含某个键
map.containsKey("zhang");
//判空
map.isEmpty();//返回值为boolean类型
//map大小
map.size();
//从键值中删除
map.remove("zhang");
//循环取值
map.put("cheng", "32");
map.put("yun", "33");
for (String key : map.keySet())
System.out.println(key);
for (String values : map.values())
System.out.println(values);
//清除map
map.clear();

4. Stack

Stack继承于Vector,因此它也包含Vector中的全部API。vector实现了List。但因为比较常用单把它摘出来。

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
Stack的基本使用
初始化
Stack stack=new Stack
判断是否为空
stack.empty()
取栈顶值(不出栈)
stack.peek()
进栈
stack.push(Object);
出栈
stack.pop();

实例:
public class Test01 {
public static void main(String[] args) {
Stack stack=new Stack();
//1.empty()栈是否为空
System.out.println(stack.empty());
//2.peek()栈顶值 3.进栈push()
stack.push(new Integer(1));
stack.push("b");
System.out.println(stack.peek());
//4.pop()出栈
stack.pop();
System.out.println(stack.peek());

}
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
1 import java.util.Stack;
2 import java.util.Iterator;
3 import java.util.List;
4
5 /**
6 * @desc Stack的测试程序。测试常用API的用法
7 *
8 * @author skywang
9 */
10 public class StackTest {
11
12 public static void main(String[] args) {
13 Stack stack = new Stack();
14 // 将1,2,3,4,5添加到栈中
15 for(int i=1; i<6; i++) {
16 stack.push(String.valueOf(i));
17 }
18
19 // 遍历并打印出该栈
20 iteratorThroughRandomAccess(stack) ;
21
22 // 查找“2”在栈中的位置,并输出
23 int pos = stack.search("2");
24 System.out.println("the postion of 2 is:"+pos);
25
26 // pup栈顶元素之后,遍历栈
27 stack.pop();
28 iteratorThroughRandomAccess(stack) ;
29
30 // peek栈顶元素之后,遍历栈
31 String val = (String)stack.peek();
32 System.out.println("peek:"+val);
33 iteratorThroughRandomAccess(stack) ;
34
35 // 通过Iterator去遍历Stack
36 iteratorThroughIterator(stack) ;
37 }
38
39 /**
40 * 通过快速访问遍历Stack
41 */
42 public static void iteratorThroughRandomAccess(List list) {
43 String val = null;
44 for (int i=0; i<list.size(); i++) {
45 val = (String)list.get(i);
46 System.out.print(val+" ");
47 }
48 System.out.println();
49 }
50
51 /**
52 * 通过迭代器遍历Stack
53 */
54 public static void iteratorThroughIterator(List list) {
55
56 String val = null;
57 for(Iterator iter = list.iterator(); iter.hasNext(); ) {
58 val = (String)iter.next();
59 System.out.print(val+" ");
60 }
61 System.out.println();
62 }
63
64 }