Java学习笔记--第三周
集合
集合是java中提供的一种容器,可以存储数据。接下来从集合的使用、遍历和特性来讲述集合。
一、Collection集合
Collection集合是所有集合的根。包含了所有集合的共用方法。
集合与数组的区别:
- 数组长度不能改变,集合长度可以改变
- 数组中储存的是同一类型的元素,可以储存基本数据类型值。集合储存的都i是对象,而且对象类型可以不一致。
Collection集合的使用:
Collection是接口,不能直接创建对象,因此需要使用多态来创建。
// 如:
Collection<String> collection = new ArrayList<>();
集合框架介绍
Collection集合常用方法
public boolean add(E e) //把给定对象添加到当前集合中
public viod clear() //清空集合中所有的元素
public boolean remove(E e) //把给定对象在当前集合中删除(如果集合中没有该元素,则删除失败,返回false)
public boolean contains(E e) //判断集合中是否含有给定元素
public boolean isEmpty() //判断当前集合是否为空
public int size() //返回集合中元素个数
public Object[] toArray() //把集合中元素存储到数组中
Collection<String> collection=new ArrayList<>();
collection.add("wo");
collection.add("de");
System.out.println(collection);//[wo, de]
collection.remove("de");
System.out.println(collection);//[wo]
boolean b=collection.contains("de");
System.out.println(b);//false
Object[] obj=collection.toArray();
for (int i = 0; i < obj.length; i++) {
System.out.println(obj[i]);//wo
}
Iterator接口
Iterator接口是一个迭代器,专门遍历Collection集合(注意:与增强for循环不同,Iterator迭代器不能遍历数组)
接口对象的创建:Iterator是一个接口,不能直接创建对象,但是可以通过Collection集合中的iterator方法返回Iterator对象。
Collection<String> collection=new ArrayList<>();
Iterator it=clooection.iterator();
接口常用方法:
public boolean hasNext() //判断集合是否有下一个元素,并迭代
public E next() //返回集合迭代的下一个元素
迭代就是将指针指向下一个元素,相当于i++
注意:这里的指针开始是0
Collection<String> collection=new ArrayList<>();
collection.add("wo");
collection.add("de");
Iterator it=clooection.iterator();
while(it.hasNext()){
System.out.println(it.next());//[wo,de]
}
增强for循环
又叫foreach循环,专门遍历数组或集合
// 格式:
// for(数组或集合数据类型 变量名:集合或数组对象){
// System.out.println(变量名);
// }
//遍历上述collection集合
for(String s:collection){
System.out.println(s);//[wo,de]
}
二、泛型
泛型是一种未知的数据类型。当对一个对象(尤其是集合)传递数据时,不知道是什么类型,这时候就可以使用泛型了。当集合不使用泛型时会默认Object类型(不建议,Object类型在使用toString方法时会报错,遍历集合时会发生数据转换,不安全)。
当使用泛型时,避免了类型转换的麻烦,储存的是什么类型,打印的就是什么类型,并且把运行期异常提升到了编译期(就是在你代码写完的时候,编译器会提醒是否报错)。
弊端:泛型是什么类型就只能储存什么类型。
定义和使用含有泛型的类
格式:修饰符 class 类名称<代表泛型的变量>()
使用泛型的类可以接受任何指定类型的数据
//定义成员变量时不能写出具体类型
public class P2<E> {
private E name;
private E age;
}
//使用的时候与ArrayList集合一模一样,用不用泛型都可以
定义和使用含有泛型的方法
格式:(成员方法)
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
public <E> void p(E e){
System.out.println(e);
}
//使用方法与正常方法没有区别
定义和使用含有泛型的接口
格式与类的定义一样,这里就不再缀续。
泛型通配符
“?”就是泛型通配符,代表任意的数据类型。
使用方法:不能创建对象使用,只能作为方法的参数。
例如:当有多个集合需要打印时,使用Iterator接口显然不方便。这时创建一个方法就很有必要。而方法中的参数就不能确定为一种数据类型,这时就到泛型通配符的使用(泛型没有继承的概念,因此不能使用Object)。
//创建一个
public static void printArrayList(ArrayList<?> list){
Iterator<?> it=list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
泛型通配符的高级使用—受限泛型
就是指定一个泛型的上限和下限
泛型的上限:
格式:类型名称<? extends 类> 对象名
意义:只能接受该类型及其子类
泛型的下限:
格式:类型名称<? super 类> 对象名
意义:只能接受该类型及其父类
//能够看懂就行,不需要掌握。
public static void nun(Collection <? extends Double> coll){}
//接受的数据类型必须是Double或其子类
三、与集合相关的数据结构
与集合相关的常用数据结构有:栈、队列、数组、链表和红黑树。
栈
栈结构共用一个出入口,因此进出有顺序(先进后出)
进栈—>入栈或压栈
出栈—>出栈或弹栈
队列
队列有一出口、一进口,所以先进先出
数组
特点:查询快,增删慢
链表
特点:查询慢,增删快
查询慢:链表中地址不是连续的,每次查询元素都必须从头开始查询。
增删快:链表结构,增加/删除一个元素,对链表整体结构没有影响,所以增删快。
链表有单项链表和双向链表之分。
红黑树
四、List集合
是一个有序的集合,与Set集合区别除了集合中元素可以重复外就是List集合有索引,可以使用get方法。主要有3个接口。
//List集合特有方法:
public void add(int index,E element) //将指定元素添加到集合指定位置。
public E get(int index) // 返回集合中指定位置元素
public E remove(int index) //移除指定位置元素
public E set(int index,E element) //用指定元素替代集合中指定位置的元素,返回值是替换前的元素
//(index是索引,要被替换元素的位置,element是替换元素)
ArrayList集合
ArrayList的数据储存结构是数组结构,因此查询快,增删慢。非常实用
LinkedList集合
LinkedList的数据储存结构是nian链表结构,因此查询慢,增删快
LinkedList集合提供了大量的操作首尾元素的方法。
public void addFirst(E e)//将指定元素插入此列表的开头。其他元素往后退一格
public void addLast(E e)//将指定元素添加到此列表的结尾。
public void push(E e)//将元素推入此列表所表示的堆栈。与addFirst一样
public E getFirst()//返回此列表的第一个元素。
public E getLast()//返回此列表的最后一个元素。
public E removeFirst()//移除并返回此列表的第一个元素。
public E removeLast()//移除并返回此列表的最后一个元素。
public E pop()//从此列表所表示的堆栈处弹出一个元素。相当于removeFirst。
–> 这里就不再一一演示了
Vector集合
是老版的单线程集合,被ArrayList集合取代了。
五、Set集合
Set集合存储数据的结构是哈希表,因此Set集合中不允许存储相同的元素。常用实现类是HashSet和LinkedHashSet。HashSet集合不重复,但无序,而LinkedHashSet有序。
哈希值:一个十进制的整数,由系统随机给出(对象的一个逻辑地址值,是模拟出来地址,不是数据实际存储的物理地址)
Object类中有一个方法可以获取对象的哈希值。
int hashCode() //返回该对象的哈希值
HashSet集合存储数据的结构(哈希表)
Set集合添加元素不重复的原理:
Set集合重写了hashCode和equals方法,在添加元素时会先调用hashCode方法获得哈希值,如果集合中没有相同的哈希值,认定元素不相同;如果哈希值相同(哈希冲突),再使用equals方法判断,如果返回false,元素不同;返回ture,元素相同。
通过两个步骤的原因是,哈希表的查询速度非常快,时间和空间复杂度都为o(1)。
HashSet存储自定义类型元素
HashSet存储元素不同的原因是存储对象重写了hashCode和equals方法,想让该集合存储自定义类型元素,就必须重写这两种方法。
IJ编译器可以一键重写。具体方法:点击菜单栏的Code,选择Generate,再选择equals() and hashCode(),最后全部确定就行了。
可变参数(底层时一个可变的数组)
使用前提:当方法的参数数据类型已经确定,但参数的个数不确定
格式:(只能作为方法的参数)修饰符 返回值类型 方法名(数据类型…变量名){}
注意事项:
- 一个方法的参数列表只能有一个可变参数
- 如果方法的参数有多个,可变参数必须写在最后面
//当n个数相加时
public static void main(String[] args) {
sum(1,2,3,4,5,6,7,8,9);//45
}
public static void sum(Integer...x){
int sum=0;
for (int i = 0; i <x.length ; i++) {
sum+=x[i];
}
System.out.println(sum);
}
未完待续…