一、集合概念
何为集合,集合就是相当于一个对象的容器。集合是类似数组的一个作用。既然有了数组,为何还要有集合呢,由于数组对象一旦创建,其大小便不可以更改,我们只能往数组中存放创建时数量的对象。而集合中的长度却是动态可变化的,我们可以往集合中添加任意数量的对象。并且我们可以通过集合更方便地实现数据结构如队列,栈等等。在集合中我们更可以定义自己想要的操作。
通俗的说,集合就是一个放数据的容器,准确的说是放数据对象引用的容器。
二、集合框架图
如图所示:图中,实线边框的是实现类,折线边框的是抽象类,而点线边框的是接口
Collection接口是最基本的集合接口,java不提供这个接口的直接的实现类。但是继承它的有两个接口:Set和List。
Set:取值时不保证数据和存入的时候顺序一致,并且不允许空值,不允许重复值。
List:一个有序的集合,和Set不同的是,List允许存储项的值为空,也允许存储相等值的存储项。
Map是Java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value。
Iterator,所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
1.hasNext()是否还有下一个元素。
2.next()返回下一个元素。
3.remove()删除当前元素
三、主要的集合的接口或类
1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。List主要分为3类:ArrayList、LinkedList和Vector
ArrayList:可变数组,允许所有元素,包括null。不同步。
LinkedList:List 接口的链接列表实现。允许所有元素,包括 null。不同步。
Vector:较早的集合类,Vector会在你不需要进行线程安全的时候,强制给你加锁,导致了额外开销,所以慢慢被弃用了。同步。
ArrayList和LinkedList在用法上没有区别,但是在功能上还是有区别的。ArrayList是基于动态数组的数据结构,LinkedList是基于链表的数据结构。有个很简单的结论,ArrayList在查询读取上优于LinkedList,在增删改查上,LinkedLIst优于ArrayList。至于深入对比,可以自行查询。
- 使用LinkedeList<Integer>实现对链表的排序(sougou笔试题)
//LinkedList<Integer>实现链表的排序 使用插入排序
public LinkedList<Integer> insertSortForLinkedList(LinkedList<Integer> list){
int len=list.size();
for(int i=1;i<len;i++) {
int j=i-1;
int temp=list.get(i);
list.remove(i);//删除元素
while (j>=0&&temp<list.get(j)) {
j--;
}
list.add(j+1,temp);
}
return list;
}
- 使用LinkedeList实现栈和队列
import java.util.*;
class Stack{
private LinkedList list;
public Stack(){
list=new LinkedList();
}
public Object top(){ //输出最上面的元素
if(list.size()!=0){
return list.getFirst();
}
return -1;
}
public void pop(){ //出栈
if(list.size()!=0){
list.removeFirst();
}
}
public void push(Object v){ //入栈
list.addFirst(v);
}
public int getLen(){
return list.size();
}
}
import java.util.*;
class Test{
public static void main(String[] args){
Stack stack = new Stack();
stack.push("张三");
stack.push(3);
stack.push("李四");
stack.push("5");
System.out.println("长度---"+stack.getLen()); //4
/**
//注意这样写是有问题的,因为在出栈的过程中stack.getLen()是会发生变化的
for(int i=0;i<stack.getLen();i++){
System.out.println(stack.top());
stack.pop();
//System.out.println("长度---"+stack.getLen()); //4
}
**/
/**
//正确
int i=stack.getLen()-1;
while(i>=0){
System.out.println(stack.top());
stack.pop();
i--;
}
**/
//正确,但是会引来不安全操作提醒
while(stack.getLen()>0){
System.out.println(stack.top());
stack.pop();
}
System.out.println(stack.top());
stack.pop();
}
}
2、Set(无序、不可重复)
一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。HashSet:不保证set的迭代顺序,特别是它不保证该顺序恒久不变(有可能变化)。允许null元素(set只能有一个null)。不同步。由哈希表(实际上是一个 HashMap 实例)支持。
TreeSet:有序(二叉排序树)。不允许null(二叉树不允许空)。
二者区别:
1、TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值。
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。
3、Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
主要实现类:HashMap、TreeMap、HashTable
HashMap:无序,不保证顺序不变。允许使用 null 值和 null 键。不同步。
HashTable:除了同步以及不允许null,其他与HashMap没有差别。
TreeMap:有序(二叉排序树)。非空。不同步。
常用方法:
clear() | 从 Map 中删除所有映射 |
remove(Object key) | 从 Map 中删除键和关联的值 |
put(Object key, Object value) | 将指定值与指定键相关联 |
putAll(Map t) | 将指定 Map 中的所有映射复制到此 map |
entrySet() | 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素 |
keySet() | 返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值) |
values() | 返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值) |
get(Object key) | 返回与指定键关联的值 |
containsKey(Object key) | 如果 Map 包含指定键的映射,则返回 true |
containsValue(Object value) | 如果此 Map 将一个或多个键映射到指定值,则返回 true |
isEmpty() | 如果 Map 不包含键-值映射,则返回 true |
size() | 返回 Map 中的键-值映射的数目 |
参考链接:http://blog.csdn.net/u014136713/article/details/52089156
https://www.cnblogs.com/leeplogs/p/5891861.html
https://www.cnblogs.com/lxq0309/p/3655742.html