一,什么是集合
集合是由多元素组成的一组数组
提供了一套性能优良、使用方便的接口和类位于Java.util包中
集合中的元素全部是对象,即Object类的实例()
不同的集合类有什么不同的功能和特点,适合不同的场合
1.1为什么要用集合:
集合弥补了数组的缺陷,比数组跟灵活,可以提高软件的开发效率,不同的集合可以应用在不同的场合 而且可以存储任意类型的值
注意:
集合中为什么可以存储任意类型的值:应为它是把传递进来的时候强制把值转换成了Object类型(这个也属于一个弊端,因为要进行频繁的转换)
值类型 引用类型 装箱拆箱
1.2、什么时候用集合:
如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架
1.3、怎么用集合:
集合类主要Collction和Map接口派生而来通过实例化他们的实例类使用即可
1.4、集合的优点:
灵活、提高了代码运行效率、可存放任意类型的值
1.5、集合和数组的区别:
数组:长度固定不变、只能存放相同类型的值
集合:长度可以改变。可以存放不同类型的值
2、Collction接口:
Collection接口存储一组可重复且没有顺序的对象
2.1、Collction接口的方法:
在输出时系统会调用toString方法
2.2、List接口:
Set接口继承了Collcetion接口可以存储:一组不可以重读且没有顺序的对象
List接口继承了Collection接口可以存储:一组可以重复且有顺序的对象
2.2.1、List接口:
继承Collection接 口,存储一组可重复的有序对象
元素顺序以元素插入的次序来放置元素,不会重新排序
通过索引访问数组元素,索引从0开始
根据索引操作集合元素的方法
2.2.2、List接口的实现类
ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素
LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素
2.2.3方法如下:
在继承了父类接口Collection的方法上拓张了一些自己特有的方法
方法 | 说明 |
---|---|
void add(int index, Object o) | 将元素插入到指定位置 |
boolean addAll(int index, Collection c) | 将集合c所有元素插入到List集合中的指定位置 |
Object get(int index) | 返回索引处的元素 |
int indexOf(Objcet o) | 返回对象o在List集合中第一次出现的地方 |
int lastIndexOf(Objcet o ) |
最后一次出现的地方 |
Object remove(int index) | 删除索引指定的元素 |
boolean remove(Object) | 从集合中删除指定元素 |
Object set(int index, Object ele) | 将索引的值替换成 ele对象 |
List subList(int fromIndex, int toIndex) | 截取颔首不含尾 |
2.2.4、ArrayList集合类(实现了List接口)的使用方法:
ArratList和数组类似,也是用一个下标代表一个值,访问也可呀通过下标(从0开始)
代码展示:
//添加元素的方法和删除的方法
List list=new ArrayList();
list.add("李四");
list.add("王五");
list.add("李三");
System.out.println(list);//输出集合
list.add(0,"张三");//在0下标添加一个值
System.out.println(list);//输出
list.remove("李四");//删除值为李四的区间
list.remove(1);//删除下标为1的值
System.out.println(list);//输出
System.out.println(list.get(0));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
注意:在ArratList进行新增和删除时,下标会自动更新
如 0下标的值为张三
1下标的值为李四
2下标的值为王五
此时把张三删除掉,则系统自动会把下标更新,所以之后0下标中的值就是李四,1下标中的值就是王五
此时如用add()方法添加的是一个对象的则遍历时需要转型
代码展示:
//创建四个狗狗对象
Dog d=new Dog("欧欧","雪瑞纳");
Dog d1=new Dog("亚亚","拉布拉多");
Dog d2=new Dog("美美","雪纳瑞");
Dog d3=new Dog("菲菲",";拉布拉多");
Dog d4=new Dog("欣欣","吉娃娃");
//创建ArrayList集合
List li=new ArrayList();
li.add(d);
li.add(d1);
li.add(d2);
li.add(d3);
li.add(d4);
//删除第三个元素
li.remove(3);
//输出狗狗的数量
System.out.println("狗狗的数量时:"+li.size());
System.out.println("分别是");
System.out.println("用for遍历");
for(int i=0;i<li.size();i++){
Dog dog=(Dog)li.get(i);//转型 由于List集合中存放的都是Object类的都西昂
所已要强制类型转换
System.out.println(dog.getName()+"\t"+dog.getBrand());
注意事项:
可以使用索引访问List集合元素
可以使用for循环遍历List集合
List集合中存放的都是Object类对象
add(Object o)方法的参数是Object类对象
在通过get(int i)方法获取元素时必须进行强制类型转换
如:Dog dog=(Dog)li.get(i);
删除集合元素的方法
按索引删除
按对象删除
调用set(int index,Object o)方法改变List集合指定索引的元素时,指定的索引必须是List集合的有效索引
set(int index,Object o)方法不会改变List集合的长度
2.3、LinkedList集合类
具有双向链表结构,更加方便实现添加和删除操作
除了具有List接口扩展的方法外,还提供了实现链表操作的方法
方法名 | 说明 |
---|---|
void addFirst(Object o) | 在链表的首部添加元素 |
void addLast(Object o) | 在链表的末尾添加元素 |
Object getFirst() | 返回链表中第一个元素 |
Object getLast() | 返回链表中最后一个元素 |
Object removeFirst() | 删除并返回链表中的第一个元素 |
Object removeLast() | 删除并返回链表中的最后一个元素 |
使用方法:
代码:
/**
* 狗类
*/
public class Dog {
private String name;/**狗的名字*/
private String brand;/**品种*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
/**
* 类的无参构造方法
*/
public Dog() {
}
/**
* 类的有参构造方法
* @param name
* @param brand
*/
public Dog(String name, String brand) {
this.name = name;
this.brand = brand;
}
}
//创建四个狗狗对象
Dog d3=new Dog("菲菲",";拉布拉多");
Dog d=new Dog("欧欧","雪瑞纳");
Dog d1=new Dog("亚亚","拉布拉多");
Dog d2=new Dog("美美","雪纳瑞");
//创建集合
LinkedList lik=new LinkedList();
lik.add(d3);
lik.add(d);
lik.add(d1);
lik.add(d2);
Dog dog=(Dog)lik.getFirst();//拿到集合中的第一个元素
Dog dog2=(Dog)lik.getLast();//拿到集合中的最后de元素
System.out.println("第一天狗叫"+dog.getName());
System.out.println("第最后狗叫"+dog2.getName());
lik.removeFirst();//删除第一个元素
lik.removeLast();//删除最后一个元素
System.out.println("删除部分的狗时");
System.out.println("还有"+lik.size()+"条");
Iterator it=lik.iterator();
while(it.hasNext()){
Dog dog44=(Dog)it.next();//转型
System.out.println(dog44.getName()+"\t"+dog44.getBrand());
运行结果:
2.4.ArrayList和LinkedList的区别
ArrayList类和LinkedList类的共同点
可以容纳所有类型的元素对象,包括null
元素值可以重复
元素按顺序存储
ArrayList类特点
底层是数组
优点:基于数组实现,读取操作效率高
缺点:不适合频繁进行插入和删除操作,因为每次执行该类操作都需要频繁移动其中的元素
LinkedList类特点
由双向链表实现,任意一个节点都可以方便地访问它的前驱节点和后继节点
优点:增加、删除操作只需修改链表节点指针,不需进行频繁的移动
缺点:遍历效率较低
3.Set接口
和List接口一样,也是Collection的子接口
集合里的多个对象之间没有明显的顺序
不允许包含重复的元素
与Collection接口基本一样,没有提供额外的方法,只是行为上略有不同
继承关系:
3.1HashSet类
说明:是Set接口的典型实现,可以实现对无序不重复数据的存储,具有很好的存取和查找性能
特征:
不允许存储重复的元素
没有索引,没有包含索引的方法,不能使用索引遍历
无序集合,存储元素和取出元素的顺序可能不一致
不能使用索引进行遍历
使用方式:
public class HashSetDemo {
public static void main(String[] args) {
Set ss=new HashSet();
System.out.println( ss.add("11"));//添加值 添加成功返回true防止false
System.out.println( ss.add("11"));//检测是否可以添加相同的值
//创建迭代器对象
Iterator<String> it=ss.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
运行结果:
3.2List和Set的区别
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
4.Map接口:
Map接口专门处理键值映射数据的存储
根据键(key)实现对值(value)的操作
Key:不要求有序,不允许重复
Value:不要求有序,但允许重复
与Collection接口不存在继承关系
常见方法:
方法 | 描述 |
---|---|
Object put(Object key,Object value) | 以“键-值对”的方式进行存储 |
Object get(Object key) | 返回指定键所对应的值。如果不存在指定的键,返回null |
int size() | 返回元素个数 |
boolean remove(Object key) | 删除指定的键映射的“键-值对” |
Set keyset() | 返回键的集合 |
Collection values() | 返回值的集合 |
boolean containsKey(Object key) | 如果存在指定的键映射的“键-值对”,则返回true |
Set entrySet() | 返回“键-值对”集合 |
boolean isEmpty() | 若不存在“键-值对”元素,则返回true |
void clear() | 删除该Map对象中的所有“键-值对” |
HashMap使用方法特别情况:
mm.put("a","e");
mm.put("a","w");
HashMap使用方法
Map mm=new HashMap();
mm.put("a","e");
mm.put("a","w");
System.out.println(mm);
mm.put("c","q");
//输出所有key
System.out.println(mm.keySet());
//输出所有values
System.out.println(mm.values());
//输出key-values
System.out.println(mm);
//遍历key
for(Object obj:mm.keySet()){
System.out.println(obj);
}
//遍历values
for(Object obj:mm.values()){
System.out.println(obj);
}
//一起遍历
for(Object obj:mm.entrySet()){
System.out.println(obj);
特点:
存储成对出现的“键-值对”元素
如:京—北京市
一个Map对象由若干个“键-值对”组成
优势:查询指定元素效率高
4.1Map.Entry接口
用于保存“键-值对”元素
运用Map.Entry接口遍历集合
通过entrySet()方法获取所有“键-值”对元素的集合
遍历集合中每个元素,进行键和值的分离
4.2Map和Map.Entry接口的联合使用
Map<String, String> mm=new HashMap();
mm.put("菲菲","拉布拉多");
mm.put("亚亚","拉布拉多");
mm.put("欣欣","吉娃娃");
mm.put("美美","雪纳瑞");
Set<String> ss=mm.keySet();//把键值放到Set集合中
System.out.println("用迭代器遍历");
Iterator<String> it=ss.iterator();
while(it.hasNext()){
String key=(String)it.next();
String name=mm.get(key);//把值放入到name中
System.out.println(key+"\t"+name);
}
System.out.println("用froech循环");
//用到了Map.Entry接口
for (Map.Entry<String,String> m: mm.entrySet()) {
System.out.println(m.getKey()+"\t"+m.getValue());
}
5.迭代器:
用处:遍历集合
常见方法:
方法 | 描述 |
---|---|
boolean hasNext() | 是否存在下一个迭代元素,存在则返回true |
Object next() | 返回迭代的下一个元素 |
void remove() | 删除集合里上一次next()方法返回的元素 |
注意事项:
Iterator的使用必依赖于Collection对象
Iterator仅用于遍历集合,并不提供储存数据的功能
使用Iterator迭代访问Collection集合时,可调用Iterator的remove()方法删除集合元素
使用Iterator对集合元素进行迭代时,是把集合元素的值传给迭代器,因此,删除迭代器中存储的值不会影响集合中保存的元素
代码展示:
Collection cc=new HashSet();
Fruit ff=new Fruit("香水梨",2.5);
Fruit ff1=new Fruit("苹果梨",2.0);
Fruit ff3=new Fruit("富士苹果",3.5);
Fruit ff4=new Fruit("金帅苹果",3.0);
cc.add(ff);
cc.add(ff1);
cc.add(ff3);
cc.add(ff4);
//输出结果
// System.out.println(cc);
//获取迭代器
Iterator it=cc.iterator();
while(it.hasNext()){
Fruit fruit=(Fruit)it.next();
fruit.show();
错误示范:
对Collection集合进行遍历操作时,其中的元素不能被改变
Iterator it = fruitList.iterator();
while(it.hasNext()) {
Fruit fruit = (Fruit)it.next();
if(fruit.brand.equals("苹果梨")) {
fruit.remove();//这是直接用集合名点的将会影响到集合
} else {
fruit.show();
}
}
产生的异常:不可以在遍历式改变集合
6.foreach遍历数组
foreach循环
JDK1.5引入的语法结构,也称为增强for循环
可用于遍历集合和数组
语法:
代码展示:
使用foreach循环遍历水果品类集合
for(Object obj:fruits) {
Fruit fruit = (Fruit)obj;
输出结果
与Iterator接口类似,foreach循环中迭代变量也不是集合元素本身,系统只是依次把集合元素的值赋给迭代变量。因此,在foreach循环中修改迭代变量的值也没有任何实际意义
7.结构图于继承图
常用的式左边
常用的式左边