Collection集合
数组:存储的是同一类型的元素,可以存储基本数据类型。
集合:存储的都是对象。
格式 | 作用 |
---|---|
boolean add(E e) | 向集合中添加元素 |
boolean remove(E e) | 删除集合中的元素 |
void clear() | 清空集合所有的元素 |
boolean contains(E e) | 判断集合中是否包含某个元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 获取集合的长度 |
Object[] toArray() | 将集合转成一个数组 |
栗子:
//创建集合对象
Collection<String> coll = new ArrayList<>();
//向集合中添加元素
coll.add("hello");
coll.add("world");
coll.add("xiaoming");
coll.add("java");
System.out.println(coll);//[hello, world, xiaoming, java]
//删除集合中的元素
boolean result1 = coll.remove(o:"hello");
System.out.println(result1);//true
System.out.println(coll);//[world, xiaoming, java]
//清空集合所有的元素
coll.clear();
System.out.println(coll);//[]
//判断集合中是否包含某个元素
boolean result2 = coll.contains("java345");
System.out.println(result2);//false
//判断集合是否为空
System.out.println(coll.isEmpty());//true
//获取集合的长度
System.out.println(coll.size());//0
//将集合转成一个数组
Object[] arr = coll.toArray();
//遍历数组
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
Iterator接口
介绍
迭代:
即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就再取出来。一直把集合中的所有与三俗全部取出。这种取出方式叫迭代。
迭代器代码的实现
常用的两个方法:
- boolean hasNext():判断集合或只能怪还有没有下一个元素,有则返回true,没有则返回false。
- E next():取出集合中的下一个元素。
Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊。
Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象。
- Iterator iterator():返回在此collection的元素上进行迭代的迭代器。
迭代器的使用步骤:
1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)。
2.使用Iterator接口中的方法hasNext()判断还有没有下一个元素。
3.使用Iterator接口中的方法next()取出集合中的下一个元素。
例如:
//创建一个集合对象
Collection<String> coll = new ArrayList<>;
//往集合中添加元素
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走
//集合是什么泛型,迭代器就是什么泛型。
Iterator<String> it = coll.iterator();
while(it.hasNext){
String e = it.next();
System.out.println(e);
}
泛型
使用泛型的好处
创建集合对象,不使用泛型
好处:
默认的类型是Object类型,可以存储任意类型的数据。
弊端:
不安全,会引发异常。
ArrayList list = new ArrayList();
list.add("abc");
list.add(1);
//使用迭代器遍历list集合
//获取迭代器
Iterator it = list.iterator();
//使用迭代器中的方法hasNext和next遍历集合
while(it.hasNext()){
//取出元素也是Object类型
Object obj = it.next();
System.out.println(obj);
//想要使用String类特有的方法,length获取字符串的长度,但是因为使用多态,所以不能使用。
//需要向下转型
String s = (String)obj;
//会抛出类型转换异常,不能把Integer转为String
System.out.println(s.length());
}
创建集合对象,使用泛型
好处:
1.避免了类型转换的麻烦,存储的是什么
2.把运行期异常(代码运行之后会抛出异常),提升到编译期(写挨骂的时候报错)。
弊端:
泛型是什么类型,只能存储什么类型的数据。
ArrayList<String> list = new ArrayList<>();
list.add("abc");
//使用迭代器遍历list集合
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s + " " + s.length());//abc 3
}
定义和使用含有泛型的类
类:
public class GenericClass<E> {
public E name;
public E getName() {
return name;
}
public void setName() {
this.name = name;
}
}
主函数:
//不写泛型默认为Object类型
GenericClass gc = new GenericClass();
gc.setName("只能是字符串");
Object obj = gc.getName();
//创建GenericClass对象,泛型使用Integer类型
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setName(1);
Integer name = gc2.getName();
System.out.println(name);
//创建GenericClass对象,泛型使用String类型
GenericClass<Integer> gc2 = new GenericClass<>();
gc3.setName("小明");
String name1 = gc3.getName();
System.out.println(name1);
定义和使用含有泛型的方法
格式:
GenericMethod类(含有成员方法和静态方法):
//定义一个含有泛型的方法
public <M> void method01(M m) {
System.out.println(m);
}
//定义一个含有泛型的静态方法
public static <S> void method02(S s) {
System.out.println(s);
}
主函数:
//创建GenericMethod对象
GenericMethod gm = new GenericMethod();
gm.method01(m:10);
gm.method01(m:"abc");
GenericMethod.method02(s:"静态方法");
定义和使用含有泛型的接口
- 含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型。
GenericInterface接口:
public interface GenericInterface<I> {
public abstract void method(I i);
}
GenericInterface接口的实现类:
public class GenericInterfaceImpl1 implements GenericInterface<String> {
@Override
public void method(String s) {
System.out.println(s);
}
}
主函数:
//创建GenericInterfaceImpl1对象
GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
gi1.method(s:"字符串");
- 含有泛型的接口,第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走。就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型。
GenericInterface接口:
public interface GenericInterface<I> {
public abstract void method(I i);
}
GenericInterface接口的实现类:
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
主函数:
//创建GenericInterfaceImpl2对象
GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
gi2.method(i:10);
GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();
gi3.method(i:6.6);
泛型通配符
?:代表任意的数据类型。
使用方式:
不能创建对象使用。只能作为方法的参数使用。
例如:
主函数:
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
}
//定义一个方法,能遍历所有类型的ArrayList集合。
//这时候我们不知道ArrayList集合使用什么数据类型,可以使用泛型的通配符?来接收数据类型。
public static void printArray(ArrayList<?> list) {
//使用迭代器遍历集合
Iterator<?> it = list.iterator();
while(it.hasNext()) {
//it.next()方法,取出的元素是Object,可以接收任意的数据类型
Object o = it.next();
System.out.println(o);
}
}
(下面的“听说是”高级用法)
- 泛型的上限限定:? extends E 代表使用的泛型只能是E类型的子类/本身。
- 泛型的下限限定:? super E 代表使用的泛型只能是E类型的父类/本身。
例如:
主函数:
public static void main(String[] args) {
Collection<Inetger> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<Integer>();
Collection<Number> list3 = new ArrayList<Integer>();
Collection<Object> list4 = new ArrayList<Integer>();
getElement1(list1);
getElement1(list2);//报错
getElement1(list3);
getElement1(list4);//报错
getElement2(list1);//报错
getElement2(list2);//报错
getElement2(list3);
getElement2(list4);
/*
类与类之间的继承关系
Integer extends Number extends Object
String extends Object
*/
}
//泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
//泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}
数据结构_栈
先进后出。。。
数据结构_队列
先进先出。。。
数据结构_数组
- 查询快:数组的地址是连续的,我们通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一元素。
- 增删慢:数组的长度是固定的,如果要增加或者删除一个元素,必须创建一个新数组,把源数组的数据复制过去。
数据结构_链表
- 查询慢:链表中地址不是连续的,每次查询元素,都必须从头开始。
- 增删快:链表结构,增加/删除一个元素,对链表的整体节后没有影响。
tip:链表中的每一个元素也称之为一个节点,一个节点包含一个数据源(存储数组),两个指针域(存储地址)。
- 单向链表:链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序可能不一样)。
- 双向链表:链表总有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合。
数据结构_红黑树(不建议看我的)
二叉树:分支不能超过两个。
平衡树:左孩子和右孩子相等。
不平衡树:左孩子!=右孩子
红黑树的特点:
趋近于平衡树,查询的速度非常快,查询叶子节点最大次数和最小次数不能超过2倍。
约束:
1.节点可以是红色的或者是黑色的。
2.根节点是黑色的。
3.叶子节点(空节点)是黑色的。
4.每个红色的节点的子节点都是黑色的。
5.任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同。
List集合
特点:
1.有序的集合。存进去和取出来的元素的顺序是一致的。
2.有索引。
3.允许储存重复的元素。
格式 | 作用 |
---|---|
public void add(int index, E element) | 将指定的元素添加到该集合指定的位置上。 |
publiv E get(int index) | 返回集合中指定位置的元素。 |
public E remove(int index) | 移除列表中指定位置的元素,返回的是被移除的元素。 |
public E set(int index, E element) | 用指定的元素替换集合中国指定位置的元素,返回的是被替换的元素。 |
LinkedList集合
- java.util.LinkedList集合 implements List接口
LinkedList集合的特点:
1.底层是一个链表结构:查询慢,增删快。
2.里面包含了大量操作首尾元素的方法。
注意:使用LinkedList特有的方法,不能使用多态。
格式 | 作用 |
---|---|
public void addFirst(E e) | 将指定元素插入此列表的开头。 |
public void addLast(E e) | 将指定元素添加到此列表的结尾。 |
public void push(E e) | 将元素推入到此列表所表示的堆栈。 |
public E getFirst() | 返回此列表的第一个元素。 |
public E getLast() | 返回此列表的最后一个元素。 |
public E removeFirst() | 移除并返回此列表的第一个元素。 |
public E removeLast() | 移除并返回此列表的最后一个元素。 |
public E pop() | 从此列表所表示地堆栈出弹出一个元素。 |
public boolean isEmpty() | 如果列表不包含元素,则返回true。 |
HashSet集合
- java.util.Set接口 extends Collection接口
Set接口的特点:
1.不允许存储重复的元素。
2.没有索引,没有索引的方法,也不能使用普通的for循环遍历。
- java.util.HashSet集合 implements Set集合
HashSet特点:
1.不允许存储重复的元素。
2.没有索引,没有索引的方法,也不能使用普通的for循环遍历。
3.是一个无序的集合,存储和取出的元素顺序可能不一致。
4.底层是一个哈希表结构(查询的速度非常的快)。