collection集合:
集合:是Java中提供的一种容器,可以用来存储多个数据。
集合和数组的区别:
- 数组的长度值固定的。集合长度是可变的
- 数组中存储的是同一种数据类型的元素,可以存储数据类型,也可以存储引用数据类型,集合存储的都是对象,而且对象的数据类型可以不一致,开发中一般当对象多的时候,使用集合来存储对象。
集合的框架:
JavaSE提供了满足各种需求的API,我们在使用API的时候,先了解其继承与接口操作的框架,才能了解何时使用哪个类。
以及类与类之间是如何彼此合作的,从而达到灵活应用
集合根据其存储结构把它分成两大类:分别是单列集合:java.util.Collection和双列集合java.util.Map,今天主要了解单列Collection集合
Collection:它是单列集合的根接口,用于存储一些列符合某种规则的元素,它有两个很重要的子接口,分别是java.util.List和java.lang.Set。其中,List接口集合特点元素有序。元素可重复,含有索引。Set接口集合特点元素不重复,没有索引.
备注:绿色是底层实现类,蓝色是接口类型
List接口:(Vector集合,ArrayList集合,LinkedList集合...)
- 有序的集合(存储和取出元素的顺序相同)
- 允许存储重复性的元素
- 有索引,可以普通的for循环遍历
Set接口:(TreeSet集合,HashSet集合(无序),LingedHashSet集合(有序)...)
- 不允许存储重复性的元素
- 没有索引(不能使用普通的for循环)
collection接口:
- 定义的是所有的单列集合中共性的API方法,所有的单列集合都可以使用共性的方法。
- 没有带索引的方法
集合框架体系的学习方式:
- 学习集合框架的顶层:掌握接口或者抽象类当中的共性的方法,所有的子类都可以使用
- 使用底层的集合框架:顶层不是接口就是抽象类,需要使用底层的子类创建对象来使用集合
collection集合的常用功能
是所有单列集合的父接口,在collection集合当中定义了所有的单列集合的共性的API方法,这些方法适用于所有的单列集合,增删改查功能。
- public boolean add(E e):把给定的对象添加到当前的集合当中
public static void demo1add(){
//public boolean add(E e):把给定的对象添加到当前的集合当中
Collection<String> collection=new ArrayList();
collection.add("小王八");
System.out.println(collection);//[小王八]
boolean b=collection.add("大王八");
//add方法,一般情况都返回true,所以可以不用接收。
System.out.println(b);//true
collection.add("12");
collection.add("123");
collection.add("1245");
System.out.println(collection);//[小王八, 大王八, 12, 123, 1245]
//System.out.println(collection.contains("123"));
}
- public void clear():清空集合当中的所有的元素。
public static void demo2clear(){
//public void clear():清空集合当中的所有的元素。
Collection<String> collection=new ArrayList<>();
collection.add("234");
System.out.println(collection);//234
collection.clear();
System.out.println(collection);//空
}
- public boolean remove(E e):把给定的对象从当前集合当中删除掉。
public static void demo3remove(){ //public boolean remove(E e):把给定的对象从当前集合当中删除掉。 Collection<String> collection=new ArrayList<>(); collection.add("234"); collection.add("789"); collection.add("123"); System.out.println(collection); //删除成功 boolean s=collection.remove("789"); System.out.println(s);//true System.out.println(collection);//234,123 //删除失败 boolean s1=collection.remove("689"); System.out.println(s1);//false System.out.println(collection);
- public boolean contains(E e):判断当前集合当中是否包含给定的对象元素。
public static void demo4contains(){
//public boolean contains(E e):判断当前集合当中是否包含给定的对象元素。
Collection<String> collection=new ArrayList<>();
collection.add("234");
collection.add("789");
collection.add("123");
System.out.println(collection);
System.out.println(collection.contains("123"));//true
System.out.println(collection.contains("124"));//false
}
}
- public boolean isEmpty();判断当前集合是个否为空。null 空。
public static void demo5isEmpty(){
// public boolean isEmpty();判断当前集合是个否为空。null 空。
Collection<String> collection=new ArrayList<>();
collection.add("234");
collection.add("789");
collection.add("123");
System.out.println(collection.isEmpty());//false
collection.clear();
System.out.println(collection.isEmpty());//true
}
- public int size():获取当前集合元素的个数,
public static void demo6size(){
// public int size():获取当前集合元素的个数,
Collection<String> collection=new ArrayList<>();
collection.add("234");
collection.add("789");
collection.add("123");
System.out.println(collection.size());//3
collection.clear();
System.out.println(collection.size());//0
}
- public Object[] toArray():把当前集合中的元素存储到一个数组当中。
public static void demo7toArray(){
// public Object[] toArray():把当前集合中的元素存储到一个数组当中。
Collection<String> collection=new ArrayList<>();
collection.add("234");
collection.add("789");
collection.add("123");
Object[] arr=collection.toArray();
System.out.println(arr);//地址值
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]+" ");//234 789 123
}
}
有关该接口的其他api方法,可自行查看api帮助文档。
迭代器Iterator:
在开发程序过程中,经常需要遍历集合当中的所有元素,针对这种情况,JDK官方又提供了一个接口
java.lang.Iterator。Iterator接口他也是集合当中的一员,但是他与Map,Collection接口不同,Collection接口和Map接口它主要是用来存储元素的,而Iterator主要是用来迭代访问Collection与Map接口当中的元素。因此我们也经常把Iterator对象称为迭代器
想要遍历Collection集合当中的元素,首先需要获取该集合的迭代器。通过迭代器完成迭代操作
获取迭代器的方法:
public Iterator Iterator():获取集合对应的迭代器,用来遍历集合中的元素。
迭代的概念
- 迭代:Collection集合元素的通用获取方式,具体实现:在每次取元素之前首先判断集合当中有没有元素。如果有,就把这个元素取出来,继续再判断,如果还有就再一次取出来,一直把集合当中的所有元素全部取出来,我们把这种取出方式在专业术语叫做迭代。
Iterator接口的常用的API方法:
- public E next():获取迭代的下一个元素
- public boolean hasNext():如果人有元素可以迭代,则返回true
迭代器的实现原理:
在调用Iterator接口当中的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回。当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,以此类推,直到hasNext方法返回false时,表示迭代器达到了集合的末尾,终止对元素的遍历。如果强硬的再取集合的元素,此时程序就会抛出没有元素java.util.NoSuchElementException
备注:Iterator<E>接口也是有泛型的,迭代器的泛型是跟着集合走的,集合当中定义的什么类型,迭代器就是什么类型。
Iterator是一个接口,无法直接使用,需要借助于Iterator它的实现类对象,获取实现类对象的方式比较特殊
Iterator<E> iterator() 返回值就是此Collection元素上要进行迭代器的迭代器对象。
迭代器使用步骤:
1.通过集合的iterator()方法获取此集合元素的迭代器实现类对象,使用Iterator接口进行接收(多态)
2.使用iterator接口中定义的方法hasNext()判断集合当中还有没有下一个元素
3.使用iterator接口中定义的方法next()取出集合当中的下一个元素
Collection<String> collection = new ArrayList<>();
collection.add("234");
collection.add("789");
collection.add("123");
//获取迭代器
Iterator<String> iterator=collection.iterator();
//hasNext()判断是否有元素
boolean s=iterator.hasNext();
System.out.println(s);//true
//next()取元素
String s1=iterator.next();
System.out.println(s1);//234
//遍历输出元素
while(iterator.hasNext())
{
System.out.println(iterator.next());//789 123
}
增强for循环:
在JDK1.5之后出现了一个新的循环结构,for each循环,一般也成为增强for循环,专门用来遍历数组和集合的。它的内部原理其实是有个迭代器Iterator,在迭代过程中,不能对集合当中的元素进行增删操作。
格式:
for(元素的数据类型 变量名:Collection集合或者是数组){
//操作代码
//......
}
主要用于遍历Collection集合或者数组,在遍历的过程中,一定不要进行增删操作。
练习:遍历数组
int[] a={1,2,3,4,5,6}
for(int s:a[]){
//此时 s 代表的是数组当中的每个元素
System.out.println(s);
}
练习2:遍历集合
Collection<String> coll=new ArrayList<>();
coll.add("姚明");
coll.add("科比");
coll.add("乔丹");
coll.add("库里");
for(String s:coll)
{
//s此时表示的就是集合当中每个元素
System.out.println(s);
}
备注:目标只能是Collection集合或者是数组,增强for循环仅仅是作为遍历操作出现,简化迭代器的操作
泛型:
是一种未知的数据类型,可以在类或者方法中预知的使用未知的数据类型。
备注:一般在创建对象的时候,将未知的数据类型确定为具体的数据类型,当没有指定泛型时,默认类型为Object类型
好处:
1.避免了数据类型的转换的麻烦,存储的是什么样的数据类型,取出的就是什么样的数据类型
2.把运行期的异常(代码运行之后会抛出的异常)提升到编译期阶段(写代码的时候就会报错)
弊端:
泛型是什么样的类型,只能存储什么类型的数据
备注:泛型也是数据类型的一部分,一般我们将类名和泛型合并一起看做数据类型。
泛型的定义与使用
泛型可以用来灵活的将数据类型应用到不同的类,方法,接口当中。将数据类型作为参数进行传递。
因为我们的集合框架体系中,大量的使用了泛型。
定义和使用含有泛型的类
修饰符 class 类名<代表泛型的变量>{
}
例如:
public class ArrayList<E>{
public boolean add(E e){}
public E get(int index){}
//...
}
备注:定义的时候使用未知的泛型的变量, 使用的时候(创建对象)确定的泛型的具体类型。
定义并使用含有泛型的方法:
修饰符 <代表泛型的变量> 返回值类型 方法名(泛型参数){}
public class A{
//定义一个带有泛型的方法
public <VIP> void show(VIP vip){
System.out.println(vip);
}
//定义一个含有泛型返回值的方法
public <ONEPIECE> ONEPIECE show02(ONEPIECE onepiece){
//....
System.out.println(onepiece.getClass());//输出类型
return onepiece;
}
//定义测试类
public class Test{
public static void main(String[] args){
//创建对象
A a=new A();
//调用带有泛型的方法
a.show("abc");//VIP vip 参数----》形参 String str="abc";
a.show(123);//Integer vip=123
a.show(3.14);//Double vip=3.14;
System.out.println(a.show02(123));//Integer 123
System.out.println(a.show02(3.14));//Double 3.14
System.out.println(a.show02("abc"));//String abc
定义并使用含有泛型的接口
修饰符 interface 接口名<代表泛型的变量>{}
public interface Collection<E>{
public void add(E e);
public Iterator<E> iterator();
}
//自定义一个泛型的接口
public interface B<T>{
public abstract void add(T t);
public abstract T get();
//...
}
使用格式:
1.定义实现类时可以直接确定泛型的类型
public class C implements B<String>{
@Override
public void add(String string){
//...
}
@Override
public String get(){
//...
}
}
2.始终不确定泛型的类型,直到创建对象的时候,确定泛型的类型
public class D<T> implements B<T>{
@Override
public void add(T t){
//...
}
@Override
public T get(){
//...
}
}
使用泛型
public class Test02{
public static void main(String[] args){
D<String> my=new D<String>();
my.add("abc");
}
}
备注:此时泛型【T的值】就是String类型