一、概述
集合是存储数据的容器
集合可以存储多个数据类型的元素(不建议,原因不方便管理)
集合只能存储引用数据类型
集合框架:
二、ArrayList,LinkedList,Vector,Stack
四者都实现List接口,所以方法调用一样,以ArrayList为例
public static void main(String[] args) {
ArrayList ArrayList = new ArrayList();
ArrayList.add(100);//底层:Integer.valueOf(100);
ArrayList.add(100.1);//底层:Double.valueOf(100.1);
ArrayList.add("张三");
for(Object obj : ArrayList){
System.out.println(obj);
}
}
会报警告,因为没有指定具体类型,虽然可以存储不同类型的数据,但不建议这样做,使用泛型:
ArrayList list = new ArrayList();
public static void main(String[] args) {
//创建ArrayList集合的对象
ArrayList<String> list = new ArrayList<String>();
//添加元素
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.add("铁柱");
list.add("狗蛋");
//插入元素
list.add(2,"大帅");
//将newList1集合中所有的元素插入到list集合的末尾位置
ArrayList<String> newList1 = new ArrayList<String>();
Collections.addAll(newList1, "aaa","bbb","ccc","ccc");
list.addAll(newList1);
//将newList2集合中所有的元素插入到list集合的指定位置
ArrayList<String> newList2 = new ArrayList<String>();
Collections.addAll(newList2, "xxx","yyy","zzz");
list.addAll(2,newList2);
//获取集合中元素的个数
int size = list.size();
System.out.println("获取集合中的集合个数:"+size);
//设置指定下标上的元素
list.set(1, "大同");
//获取指定下标上的元素
String str = list.get(1);
System.out.println("获取指定下标上的元素"+str);
//清空集合中所有的元素
//list.clear();
System.out.println("判断此集合中是否包含某个元素:"+list.contains("张三"));
System.out.println("判断此集合中是否包含另一个集合:"+ list.containsAll(newList1));
System.out.println("获取元素在集合中第一次出现的下标:"+list.indexOf("张三"));
System.out.println("获取元素在集合中最后一次出现的下标:"+list.lastIndexOf("ccc"));
System.out.println("判断集合中是否没有元素:"+list.isEmpty());
//根据元素删除元素
list.remove("大同");
//根据下标删除元素
list.remove(12);
//从list集合中删除newList2中包含的所有元素 - 去除交集
list.removeAll(newList2);
//保交集
list.retainAll(newList1);
//将集合转换为字符串
Object[] arr = list.toArray();
System.out.println("将集合转换为字符串:"+ Arrays.toString(arr));
//获取集合中从开始下标处(包含)到结束下标处(不包含)的元素,并返回新的集合
List<String> subList = list.subList(1, 2);
System.out.println("截取元素:"+Arrays.toString(subList.toArray()));
//遍历1for循环
System.out.println("for循环");
for(int i =0;i<list.size();i++){
System.out.println(list.get(i));
}
System.out.println("---------------------------");
System.out.println("foreach循环");
//遍历2foreach循环
for(Object obj : list){
System.out.println(obj);
}
System.out.println("---------------------------");
System.out.println("iterator");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
}
LinkedList 相比 ArrayList新增方法:
list.removeFirst();(队列,先进先出)
list.removeLast();(栈,先进后出)
Vector属于元老级别的类,在JDK1.0开始就有的集合类,那时还没有集合框架的概念,集合框架的概念是从JDK1.2版本开始才有的概念,JDK1.2开始java重点推广集合框架的概念,当时多数程序员习惯使用Vector类,所以java又将Vector多实现了一个接口(List),才将其保留下来
public static void main(String[] args) {
Vector<String> v = new Vector<String>();
v.addElement("张三1");
v.addElement("张三2");
v.addElement("张三3");
v.addElement("张三4");
//根据下标和元素删除元素
v.remove(2);
v.remove("张三1");
Enumeration<String> elements = v.elements();
while(elements.hasMoreElements()){
String element = elements.nextElement();
System.out.println(element);
}
}
Stack:特点:栈的数据结构 - 先进后出
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
//将元素压入栈顶
stack.push("张三1");
stack.push("张三2");
stack.push("张三3");
stack.push("张三4");
//获取栈顶元素
String peek = stack.peek();
System.out.println("获取栈顶元素:"+peek);
//删除栈顶元素,并返回
//String pop = stack.pop();
//System.out.println("删除栈顶元素,并返回:" + pop);
//查询该元素距离栈顶的长度(从1开始)
int search = stack.search("张三1");
System.out.println("查询该元素距离栈顶的长度(从1开始)"+search);
//判断集合中是否没有元素 (没有元素-true 有元素-fasle)
boolean empty = stack.isEmpty();
System.out.println("判断集合中是否没有元素 "+empty);
//遍历
while(!stack.isEmpty()){
String pop = stack.pop();
System.out.println(pop);
}
}
三、Iterator、ListIterator
Iterator VS ListIterator
Iterator:正序遍历、删除
ListIterator:正序遍历、倒叙遍历、指定下标开始进行遍历、删除、添加、替换
foreach底层时使用Iterator
for(String str :list){
System.out.println(str);
}
for(Iterator<String> it = list.iterator();it.hasNext();System.out.println(element)){
element = it.next();
}
在用Iterator遍历时对集合进行增删查改操作时,要使用遍历器的方法,而不能使用集合的方法
四、HashSet、LinkedHashSet、TreeSet
存入顺序:
1.获取对象的hash值
2.通过散列算法计算出在HashSet数组中的下标
取出顺序:
从头到尾遍历数组
不能操作下标
LinkedHashSet extends HashSet
LinkedHashSet有序 + 去重
为什么是有序:
存入顺序(和HashSet步骤一样):
1.获取对象的hash值
2.通过散列算法计算出在HashSet数组中的下标
取出顺序 – 双向链表:
找到第一个添加的节点,再依次找到第二个、第三个
TreeSet的特点:自然排序
自然排序的理解:根据元素的类型自动排序
TreeSet底层数据结果为平衡二叉树
小的放左边、大的放右边
内置比较器 – Comparable
需求:编写学生类,规定排序规则:按照年龄排序(年龄相同的学生认为是同一个学生,不用存储在TreeSet中)
Student.java
public class Student implements Comparable<Student>{
private String name;
private char sex;
private int age;
private String classId;
private String id;
省略无参构造、有参构造、getter、Setter
//规定排序规则:按照年龄排序(年龄相同的学生认为是同一个学生,不用存储在TreeSet中)
@Override
public int compareTo(Student o) {
return this.age-o.age;
}
}
Test
public class Test {
public static void main(String[] args) {
TreeSet<Student> set = new TreeSet<>();
set.add(new Student("张三",'男',12,"2213","001"));
set.add(new Student("李四",'男',11,"2213","002"));
set.add(new Student("王五",'女',16,"2211","003"));
set.add(new Student("铁蛋",'女',21,"2211","004"));
set.add(new Student("铁柱",'男',13,"2213","005"));
set.add(new Student("狗子",'女',11,"2213","006"));
set.add(new Student("狗蛋",'男',12,"2211","007"));
set.add(new Student("杨过",'女',22,"2213","001"));
set.add(new Student("王淼",'男',17,"2213","002"));
set.add(new Student("问问",'男',12,"2213","003"));
for(Student stu : set){
System.out.println(stu);
}
}
}
外置比较器 – Comparator
需求:排序规则:按照名字长度排序,名字长度一致按照年龄排序,年龄也一致就不管了
Test
public class Test04 {
public static void main(String[] args) {
TreeSet<Student> set = new TreeSet<Student>(new Comparator<Student>(){
//排序规则:按照名字长度排序,名字长度一致按照年龄排序,年龄也一致就不管了
@Override
public int compare(Student o1, Student o2) {
int len1 = o1.getName().length();
int len2 = o2.getName().length();
if(len1!=len2)
{
return len1-len2;
}
int age1 = o1.getAge();
int age2 = o2.getAge();
if(age1 != age2){
return age1-age2;
}
return 1;
}
});
set.add(new Student("张三1",'男',12,"2213","001"));
set.add(new Student("李四",'男',11,"2213","002"));
set.add(new Student("王五22",'女',16,"2211","003"));
set.add(new Student("铁蛋",'女',21,"2211","004"));
set.add(new Student("铁柱333",'男',13,"2213","005"));
set.add(new Student("狗子1231",'女',11,"2213","006"));
set.add(new Student("狗蛋",'男',12,"2211","007"));
set.add(new Student("杨过",'女',22,"2213","001"));
set.add(new Student("王淼",'男',17,"2213","002"));
set.add(new Student("问问",'男',12,"2213","003"));
for(Student element : set){
System.out.println(element);
}
}
}
五、泛型
class 类名<泛型>
E - element - 元素
T - Type - 类型
K - Key - 键
V - value - 值
含义:泛型是数据安全的做法,规定数据的类型
注意:只能使用引用数据类型去规定泛型
//? 表示任意类型
public static ArrayList<?> method01(){
//ArrayList<Object> list = new ArrayList<>();
//ArrayList<Integer> list = new ArrayList<>();
ArrayList<String> list = new ArrayList<String>();
return list;
}
//? extends A:表示 A类或A的子类
public static ArrayList<? extends A> method02(){
//ArrayList<A> list = new ArrayList<>();
ArrayList<B> arrayList = new ArrayList<B>();
return arrayList;
}
//? super A:表示A类或A的父类
public static ArrayList<? super A> method03(){
//ArrayList<Object> arrayList = new ArrayList<Object>();
ArrayList<A> arrayList = new ArrayList<A>();
return arrayList;
}