什么是集合?
概念:
对象的容器,定义了对多个对象进行操作的常用方法,可以实现数组功能。
和数组的区别?
(1)数组长度固定,集合长度不固定
(2)数组可以存储基本类型和引用类型,集合只能存储引用类型
Collection体系?
Collection:List+Set
List:ArrayList+LinkedList+Vector
Set:HashSet+TreeSet(实现自SortedSet接口)
//Collection,List,Set,SortedSet都是接口
个人理解:
Java的集合都是由三个接口派生而出的,即Collection,Map,Iterator 为什么List接口和Set接口要继承自Collection呢? 假如想要造车你会去定义一些抽象方法,然后再往下细分,你可能会造汽车,卡车,汽车和卡车都是车,它俩共同的特点 就可以继承自父类车,所以Collection内的东西是List和Set共性的东西 接口(里面只放抽象方法,用来定义规范) | 抽象类(里面一方面继承了接口的方法,一方面可以自己实现一部分通用方法,还有一部分抽象方法) | 普通类(也叫实现类,用来实现前面接口和抽象类中的抽象方法,是要具体实现功能的)
对Collection接口的介绍?
Collection接口?
某些方法:
removeAll方法:如集合A有1234,集合B有12,则A.removeAll(B),A就剩下34了。即A-B
retainAll方法:取两个集合的交集,即A∩B
collection接口的操作:
Collection collection = new ArrayList();
//1.增加操作
collection.add("地瓜");
collection.add("葡萄糖");
collection.add("西瓜汁");
//System.out.println(collection.size());//输出3
//2.删除操作
collection.remove("地瓜");
System.out.println(collection.size());//输出2,删除了地瓜
collection.clear();
System.out.println(collection.size());//输出0,将集合的元素清空
//3.遍历(重点)
//3.1增加for,collection集合不能使用for,因为没有下标
for(Object o : collection){
System.out.println(o);//输出地瓜,葡糖糖,西瓜汁
}
//3.2使用迭代器,专门用来遍历集合的一种方法
Iterator iterator = collection.iterator();
/*
查找API,Iterator接口有三个方法
hasNext():如果仍有元素可以迭代,则返回true,即有没有下一个元素
next():返回迭代的下一个元素,即获取下一个元素
remove:从迭代器指向的collection中移除迭代器返回的最后一个元素,即删除当前元素
*/
System.out.println("迭代器遍历:");
while(iterator.hasNext()){
String s = (String) iterator.next();
System.out.println(s);
//collection.remove(s);//在迭代的过程中,不能使用collection的方法去删除元素,只能用iterator中的删除方式
//iterator.remove();
System.out.println(collection.size());
}
//4.判断
System.out.println(collection.contains("西瓜"));
System.out.println(collection.isEmpty());//判断是否为空
Collection collection = new ArrayList();
//添加数据
Students s1 = new Students("张三",18);
Students s2 = new Students("李四",19);
Students s3 = new Students("王二麻子",20);
collection.add(s1);
collection.add(s2);
collection.add(s3);
//System.out.println(collection.size());
//System.out.println(collection.toString());
//删除
//collection.remove(s1);
//collection.clear();//将三个对象在集合中清除,但这个三个对象还存在,因为在假如集合时,只是把地址加进集合了
//遍历
//增加for
System.out.println("增强for:");
for(Object o:collection){
System.out.println(o);
}
//迭代器
System.out.println("迭代器:");
Iterator it = collection.iterator();
while(it.hasNext()){
Students s = (Students)it.next();
System.out.println(s);
}
//判断
System.out.println(collection.contains(s1));
System.out.println(collection.isEmpty());
}
List接口?
特点:有序,顺序时添加时的顺序,有下标(遍历时可以用下标来操作,插入时可以插入到指定位置,可以通过下标获取元素),元素可重复
List实现类
ArrayList:数组结构实现,查询快,增删慢,运行效率快,线程不安全
LinkedList:双向链表结构实现,增删快,查询慢
Vector:数组结构实现,查询快,增删慢,运行效率慢,线程安全
ArrayList和LinkedList区别:
1.ArrayList必须开辟连续空间,查询快,增删慢,LinkedList无需开辟连续空间,查询慢,增删快
对List接口的操作:
List list = new ArrayList();
//1.添加
list.add("香蕉船");
list.add(0,"臭番薯");
list.add(0,"烂鸟蛋");
System.out.println(list);//[烂鸟蛋, 臭番薯, 香蕉船]
//2.删除
list.remove("香蕉船");
list.remove(0);
//System.out.println(list);//[臭番薯]
//3.遍历
//3.1增强for
System.out.println("增强for:");
for(Object o : list){
System.out.println(o);
}
//3.2迭代器
System.out.println("迭代器:");
Iterator it = list.iterator();
while(it.hasNext()){
String s = (String) it.next();
System.out.println(s);
}
//3.3使用for
System.out.println("普通for:");
for(int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
//3.4列表迭代器
//ListIterator可以向前向后遍历,添加,删除,修改元素
System.out.println("列表迭代器:");
System.out.println("从前往后:");
ListIterator listIterator = list.listIterator();
while(listIterator.hasNext()){
System.out.println(listIterator.nextIndex()+" "+listIterator.next());//打印下个元素下标和下个元素
}
System.out.println("从后往前:");
//默认情况下,指针是第一个元素之前,要先遍历到最后,才能再往前遍历
while(listIterator.hasPrevious()){
System.out.println(listIterator.previousIndex()+" "+listIterator.previous());
}
//4.判断
System.out.println(list.contains("香蕉船"));
System.out.println(list.isEmpty());
//5.获取位置
System.out.println(list.indexOf("香蕉船"));
}
代码简述:实现List接口的实现类ArrayList,LinkedList,Vector的遍历方式有普通for循环,增强for循环,普通迭代器和列表迭代器。
ArrayList的底层结构和源码分析
先说结论
1.ArrayList可以加入null 2.ArrayList底层由数组实现数据存储 3.ArrayList基本等同于Vevtor,除了ArrayList是线程不安全的,但执行效率高,在多线程的情况下,不建议用ArrayList,即方法中没有synchronized修饰
4.ArrayList中维护了一个Object类型的数组elementData, transient Object[] elementData; transient表示瞬间,短暂的,表示该属性不会被序列化,会被忽略。什么是序列化,为什么要序列化 - 剑神西门吹雪 - 博客园 5.当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,没有分配空间 第一次添加,则扩容elementData为10,如需要再次扩容,即10个空间已经满了,继续添加则扩容elementData为1.5倍,即15个,当15个再满了,再添加时则数组扩容成22个 6.如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如国需要再次扩容,则直接扩容elementData为1.5倍
//ArrayList使用
public class Demo5 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList();
//添加元素
Animal a1 = new Animal("小狗",5);
Animal a2 = new Animal("小猫",6);
arrayList.add(a1);
arrayList.add(a2);
//删除元素
//arrayList.remove(a1);
arrayList.remove(new Animal("小狗",5));
/*
这样不能删除集合中的这个元素,因为调用remove时候,会调用equals()方法,判断this==obj,
即判断传入的这个对象是否等于先前集合里的那个,传入的是obj,集合中每个对象都传入这个obj,
但==是判断的是地址,但这个是两个对象,所以不能删除
要想删除的话需要重写Animal中equals方法
*/
System.out.println(arrayList.size());
}
}
class Animal{
String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
@Override
public boolean equals(Object obj) {
//判断是不是一个对象
if(this == obj){
return true;
}
//判断传入需要删除的对象是否为空
if(obj==null){
return false;
}
//判断传入的对象是否与集合对象是一个类型
if(obj instanceof Animal){
Animal animal = (Animal)obj;
//比较属性
if(animal.name == this.name && animal.age == this.age)
return true;
}
return false;
}
}
代码简述:ArrayList的操作,遍历跟上面list中的相同,这里着重介绍了利用重写equals方法去删除集合中的元素。
LinkedList
//LinkedList演示
public class Demo7 {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
Worker w1 = new Worker("xiaoz",15);
Worker w2 = new Worker("xiaoa",19);
linkedList.add(w1);
linkedList.add(w2);
linkedList.add(w2);
System.out.println(linkedList.size());
//删除
//linkedList.remove(w1);
//System.out.println(linkedList.size());
//遍历
//普通for
System.out.print("普通for遍历:");
for(int i = 0;i<linkedList.size();i++){
System.out.println(linkedList.get(i));
}
//增强for
System.out.print("增强for遍历:");
for(Object w : linkedList){
Worker wo = (Worker)w;
System.out.println(wo);
}
//迭代器
System.out.print("普通迭代器遍历:");
Iterator it = linkedList.iterator();
while (it.hasNext()){
Worker wo = (Worker) it.next();
System.out.println(wo);
}
//列表迭代器
System.out.print("列表迭代器遍历:");
ListIterator listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
System.out.println(listIterator.next());
}
//判断
System.out.println(linkedList.contains(w1));
System.out.println(linkedList.isEmpty());
//获取某个元素的下标
System.out.println(linkedList.indexOf(w1));
}
}
class Worker{
String name;
int age;
public Worker(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
代码简述:
Vector
//Vecotr演示
public class Demo6 {
public static void main(String[] args) {
Vector vector = new Vector();
vector.add("草莓");
vector.add("芒果");
//遍历,在jdk1.2之前遍历Vector用枚举器,与迭代器类似,枚举器没有删除的方法
Enumeration en = vector.elements();
while(en.hasMoreElements()){
String o = (String)en.nextElement();
System.out.println(o);
}
}
}
代码简述:演示Vector,主要是Vector的枚举器
Set接口?
特点:无序,无下标,元素不能重复
对Set接口的操作:
//以HashSet讲解Set接口的使用
Set set = new HashSet();
set.add("joker");
set.add("lucy");
set.add("joker");
set.add(null);
//存放数据无序(添加的顺序和取出的顺序不一致,但每次运行时取出的顺序一样)
System.out.println(set);//[null, joker, lucy]
//使用迭代器遍历
Iterator iterator = set.iterator();
while(iterator.hasNext()){
String it = (String)iterator.next();
System.out.println(it);
}
//增强for循环
//增强for循环的底层也是迭代器
for(Object s : set){
System.out.println(s);
}
代码简述:基本操作和遍历
HashSet
HashSet实际上是HashMap
HashSet hashSet = new HashSet();
/*
在执行add方法后,会返回一个Boolean值
添加成功返回true
添加失败返回false,当添加重复元素时,就会返回false
*/
System.out.println(hashSet.add("xiaoa"));
System.out.println(hashSet.add("xiaob"));
System.out.println(hashSet.add("xiaoc"));
System.out.println(hashSet.add("xiaoc"));
hashSet.remove("xiaoa");
代码简述:add方法有Boolean返回值
//两个对象名字相同,但只是名字碰巧相同了,但不是一只猪,所以都可以加进去
/*
因为底层比对元素是否相同时,比对的是地址,这里如果想要两个名字相同的对象不能同时加入
需要重写这个对象的equals方法
*/
System.out.println(hashSet.add(new Pig("zhua")));//true
System.out.println(hashSet.add(new Pig("zhua")));//true
//第一个能加入,第二个加入不了
System.out.println(hashSet.add(new String("zhub")));//true
System.out.println(hashSet.add(new String("zhub")));//false
System.out.println(hashSet);
代码简述:add方法的深入理解,需要看add方法的源码,这里时间关系先不看了,以后再看
TreeSet
TreeSet能自动按有序顺序排列对象,比如按132顺序加入元素,则可以输出123,按acb顺序加入元素,则可以输出abc。
Map接口
Map接口的特点
1.Map接口和Collection接口并列存在,用于保存具有映射关系的数据:key-value
2.Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
3.Map中的key不允许重复,原因和HashSet一样(需要追源码),value可以重复
5.key和value都可以为null,但是key为null只能有一个,value为null可以有多个
6.常用String类作为Map的key
7.key和value之间存在单向一对一的关系,即通过指定的key总能找到对应的value。
HashMap
特点:HashMap按无序形式存储对象
public class Demo13 {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
hashMap.put("L1",1);
hashMap.put("L2",2);
hashMap.put("L3",3);
System.out.println(hashMap.size());//3
System.out.println(hashMap);//{L1=1, L2=2, L3=3}
hashMap.remove("L1");
System.out.println(hashMap.size());//2
System.out.println(hashMap);//{L2=2, L3=3}
System.out.println(hashMap.get("L2"));//2
System.out.println(hashMap.size());//2
hashMap.clear();
System.out.println(hashMap.size());//0
}
}
代码简述:HashMap的简单应用
TreeMap
特点:TreeMap按有序顺序创建对象,有序顺序可以改善对象的检索过程
public class Demo14 {
public static void main(String[] args) {
TreeMap treeMap = new TreeMap();
treeMap.put(1,"a");
treeMap.put(3,"c");
treeMap.put(4,"d");
treeMap.put(2,"l");
System.out.println(treeMap);//{1=a, 2=l, 3=c, 4=d}
}
}
代码简述:TreeMap的简单应用