一、集合概述
集合与数组:
数组(可以存储基本类型数据)是用来存储数据的一种容器,能够快速的进行存取,但是只能存储同一类型数据,而且需要连续的内存空间存储,长度一旦定义就不能再改变,但是我们需要存储的数据的数量是变化的,结构是多样的,一种数组结构显然不能满足所有的需求,于是就有了各种各样的数据结构,Java中对于各种数据结构的实现,就是我们用到的集合。
二、集合体系概述
Java的集合框架是由很多接口、抽象类、具体类组成的,都位于java.util包中。
三、Collection 接口
Collection接口作为单列集合中顶级接口,里面定义了单列集合共有的方法,方法以增、删、改、查、判断、转换为主,其子接口Set和List分别定义了存储方式。
● List中的数据对象有顺序且可以重复。
● Set中的数据对象没有顺序且不可以重复。
注意:
集合是容器,可以存储不同的数据,严格上讲集合中是可以存储任何类型的(只能存储引用类型),但是我们一般建议在集合中存储同类型数据。
补充:
Collection<E>,ArrayList<E>后面<E>是jdk5之后的语法---泛型,可以通过泛型语法,为集合设置一个类型,这样就只能存储设置的数据类型。
Collection接口中定义了一些集合中的共有方法:
常用方法:
①boolean add(Object element);
-
向集合末尾添加元素
②addAll(Collection coll);
-
把一个集合添加到另一个集合
③void clear();
-
清空集合中的元素,不是将集合对象变为null,而是将集合对象变为一个空集合
④int size();
-
获取集合中实际存在的元素的个数
⑤boolean isEmpty();
-
判断集合中元素的个数是否为空
⑥boolean remove(Object element);
-
删除指定元素,成功返回true,没有返回false
⑦boolean retainAll(Collection c);
-
求交集,集合数据发生变化返回true,不变返回false
案例:
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDmeo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Collection<String> c1 = new ArrayList<>();
c1.add("a");
c1.add("b");
c1.add("c");
//向集合末尾添加元素
c1.add("d");
//把一个集合添加到另一个集合
c1.addAll(c);
//清空集合中的元素
c.clear();
//比较两个集合中的内容是否相等
System.out.println(c.equals(c1));
//判断集合中元素的个数是否为空
System.out.println(c.isEmpty());
//删除指定元素,成功返回true,没有返回false
System.out.println(c.remove("h"));
//在c中保留c1中交集的元素,发生变化返回true,没有变化返回false
System.out.println(c.retainAll(c1));
//数组长度length,字符串长度length(),集合长度size()
System.out.println(c.size());
}
}
三、List 接口及实现类
List继承了Collection接口,有三个实现的类
1.ArrayList :底层是通过数组实现的,是可以边长的,查询快,中间增删慢(因为后面的元素位置要发生改变)。
-
ArrayList的常用方法 :
①add(int index, E element)
-
在指定位置添加元素
②get(int index)
-
返回列表中指定位置
③remove(int index)
-
删除并返回指定位置元素
④removeRange(int fromIndex, int toIndex)
-
删除指定区间的元素(子类继承使用)
⑤set(int index, E element)
-
将索引位置元素替换为元素element并返回被替换的元素
案例:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ArrayListDemo1 {
public static void main(String[] args) {
/*
add();向集合中添加元素时,底层会默认创建一个长度为10的Object类型数组,
当数组装满时,再次添加元素,会创建一个原来数组长度1.5倍的新数组,
将原数组内容复制过来,最后将新数组地址赋给底层的数组。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
if (minCapacity - elementData.length > 0)
grow(minCapacity);底层扩展的方法
*/
//List<String> list = new ArrayList<>();
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("d");
list.add("d");
list.add("d");
list.add(0, "X");//向指定下标位置上添加元素
System.out.println(list.get(11));//elementData[index];
System.out.println(list.remove(0));//删除并返回指定位置的元素
list.set(2, "K");//替换指定位置的元素
System.out.println(list.size());//返回集合中实际存储的元素个数
}
}
2.LinkedList: 底层是链表实现查询慢(必须从头/尾开始查找,直到找到),中间增删快,只需要改变后继节点位置。
-
LinkedList的常用方法:
①add(int index,Object element)
-
在指定位置添加元素
②addFirist(Object element)
-
将指定元素添加到此列表的开头
③addLast(Object element)
-
将指定元素添加到此列表的末尾
④get(int index)
-
返回此列表指定位置的元素
⑤removeFirst()
-
删除并返回此列表的第一个元素
⑥removeLast()
-
删除并返回此列表的最后一个元素
⑦remove(int index)
-
删除并返回指定位置的元素
⑧getFirst()
-
返回此列表的第一个元素
⑨getLast()
-
返回此列表的最后一个元素
案例:
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> llist = new LinkedList<>();
llist.add("a");//向链表中添加元素
llist.add("b");
llist.add("c");
llist.add("d");
llist.add("e");
//要找的元素位置小于size/2,从头结点开始查找,否则从尾结点开始查找
System.out.println(llist.get(3));
llist.addFirst("X");
llist.addLast("Y");
System.out.println(llist.removeFirst());
System.out.println(llist.removeLast());
System.out.println(llist);
}
}
3.Vector :底层是数组实现,线程安全的。
案例:
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
/*
* 底层也是数组实现,但是是线程安全的
*/
Vector<String> v = new Vector<>();
v.add("a");
v.add("b");
v.add("c");
v.add("d");
v.add("a");
}
}
四、遍历List的三种方式
方式一:for循环遍历:遍历集合时,可以从中删除元素
注意: 删除元素后,元素向前移动,索引++,可能会出现错漏问题
import java.util.ArrayList;
public class ListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for(int i = 0; i < a1.size();i++){
System.out.println(a1.get(i));
}
}
}
方式二:增强for循环的遍历:在遍历的过程中不能删除元素 ,
如果删除会抛出ConcurrentModificationException(并发修改异常)
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for(String s : list){
System.out.println(s);
}
}
}
方式三:迭代器遍历(Iterator)
import java.util.ArrayList;
import java.util.ListIterator;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("d");
list.add("d");
list.add("d");
list.add("d");
list.add("d");
list.add("d");
/*
迭代器遍历List集合2
针对List接口下的集合类还提供listIterator()
*/
//从指定的位置开始遍历
ListIterator<String> it = list.listIterator(2);
while(it.hasNext()){
String e = it.next();
System.out.println(e);
}
//从指定的位置开始遍历(逆序遍历)
ListIterator<String> it = list.listIterator(list.size());
while(it.hasPrevious()){
String e = it.previous();
System.out.println(e);
}
}
}
五、Set 接口
Set接口继承了Collection接口,Set中所存储的元素是不重复的,但是是无序的,Set中的元素是没有索引的
Set接口有两个实现类:
1.HashSet
HashSet 存储的元素顺序不固定
底层数据结构:哈希表+链表,哈希表依赖于哈希值存储
案例:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.TreeSet;
public class HashSetDemo {
public static void main(String[] args) {
/*
无序且不重复的集合
public HashSet() {
map = new HashMap<>(); 底层使用的是HashMap实现的.
}
*/
HashSet<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("z");
set.add("x");
set.add("x");
set.add("x");
System.out.println(set);
ArrayList<String> list = new ArrayList<>();
list.add("d");
list.add("d");
list.add("a");
list.add("d");
list.add("x");
list.add("b");
list.add("c");
HashSet<String> set1 = new HashSet<>(list);
System.out.println(set1);
TreeSet<String> set2 = new TreeSet<>(list);
System.out.println(set2);
}
}
2.TreeSet
可以给Set集合中的元素进行指定方式的排序,存储的对象必须实现Comparable接口。
底层数据结构:二叉树(红黑树是一种自平衡的二叉树)
案例:
public class Car implements Comparable<Car>{
private int no;
private String name;
public Car(int no, String name) {
super();
this.no = no;
this.name = name;
}
@Override
public int compareTo(Car o) {
return this.no-o.no;
}
@Override
public String toString() {
return "Car [no=" + no + ", name=" + name + "]";
}
}
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
/*
有序(可以根据元素自然顺序排序) 且 不能存储重复元素
public TreeSet() {
this(new TreeMap<E,Object>());
}
*/
TreeSet<String> set = new TreeSet<>();
set.add("c");
set.add("b");
set.add("z");
set.add("a");
set.add("x");
set.add("x");
System.out.println(set);
Car car1 = new Car(1,"baoma1");
Car car2 = new Car(2,"baoma2");
Car car3 = new Car(3,"baom3");
TreeSet<Car> carset = new TreeSet<>();
carset.add(car1);
carset.add(car3);
carset.add(car2);
System.out.println(carset);
}
}
六、Set 接口集合迭代
遍历方式 :
方式一:增强for循环
方式二:迭代器遍历