目录
一、集合概述
- 数组和集合的区别
- 相同点:都是容器,可以存储多个数据
- 不同点:
- 数组的长度是不可变的,集合的长度是可变的
- 数组可以存基本数据类型和引用数据类型;集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类
- 集合类体系结构
- 蓝色表示接口;红色表示实现类
- 蓝色表示接口;红色表示实现类
二、Collection集合
1、Collection集合概述
-
Collection集合概述
- 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现;它提供更具体的子接口(如Set和List)实现
-
创建Collection集合的对象
- 多态的方式创建
- 具体的实现类ArrayList
-
Collection集合常用方法
方法名 说明 boolean add(E e) 添加元素 boolean remove(Object o) 从集合中移除指定的元素 boolean removeIf(Object o) 根据条件进行移除 void clear() 清空集合中的元素 boolean contains(Object o) 判断集合中是否存在指定的元素 boolean isEmpty() 判断集合是否为空 int size() 集合的长度,也就是集合中元素的个数
import java.util.ArrayList;
import java.util.Collection;
public class MyCollectonDemo2 {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>();
// boolean add(E e) 添加元素
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
collection.add("dddd");
//System.out.println(collection);
//method1(collection);
//method2(collection);
//method3(collection);
//method4(collection);
//method5(collection);
//method6(collection);
}
private static void method6(Collection<String> collection) {
// int size() 集合的长度,也就是集合中元素的个数
int size = collection.size();
System.out.println(size);
}
private static void method5(Collection<String> collection) {
// boolean isEmpty() 判断集合是否为空
collection.clear();
boolean result = collection.isEmpty();
System.out.println(result);
}
private static void method4(Collection<String> collection) {
// boolean contains(Object o) 判断集合中是否存在指定的元素
boolean result = collection.contains("a");
System.out.println(result);
boolean result2 = collection.contains("aaa");
System.out.println(result2);
}
private static void method3(Collection<String> collection) {
// void clear() 清空集合
//就是将集合中所有的元素全部删除.
collection.clear();
System.out.println(collection);
}
private static void method2(Collection<String> collection) {
// boolean removeif(Object o) 根据条件进行删除
//removeif底层会遍历集合,得到集合中的每一个元素
//s依次表示集合中的每一个元素
//就会把这每一个元素都到lambda表达式中去判断一下
//如果返回的是true,则删除
//如果返回的是false,则保留不删除.
//boolean test(String t);
collection.removeIf(
(String s)->{
return s.length() == 3;
}
);
System.out.println(collection);
}
private static void method1(Collection<String> collection) {
// boolean remove(Object o) 从集合中移除指定的元素
//如果删除成功了,则返回true
//如果删除失败了,则返回false
boolean result1 = collection.remove("aaa");
boolean result2 = collection.remove("ddd");
System.out.println(result1);
System.out.println(result2);
System.out.println(collection);
}
}
2、Collection集合遍历
- 迭代器介绍:迭代器,集合的专用遍历方式
Iterator<E> iterator()
,返回此集合中元素的迭代器,通过集合对象的iterator()方法得到 - Iterator中的常用方法
boolean hasNext()
:判断当前位置是否有元素可以被取出E next()
:获取当前位置的元素,将迭代器对象移向下一个索引位置
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class MyCollectonDemo3 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
//1,获得迭代器的对象
//迭代器对象一旦被创建出来,默认指向集合的0索引处
Iterator<String> it = list.iterator();
//利用迭代器里面的方法进行遍历
//当前位置是否有元素可以被取出
// System.out.println(it.hasNext());
// //取出当前位置的元素 + 将迭代器往后移动一个索引的位置
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
while(it.hasNext()){
System.out.println(it.next());
}
}
}
- 迭代器中删除的方法
void remove()
:删除迭代器对象当前指向的元素
- for方式实现删除
- 当集合中要删除的元素有多个并且相邻的时候,如果没有i–就无法删除干净;这个是因为集合是自动伸缩的,当删除一个元素后,被删除元素之后的元素就会向前移动
import java.util.ArrayList;
public class MyCollectonDemo4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if("b".equals(s)){
list.remove(i);
i--;
}
}
System.out.println(list);
}
}
- 迭代器方式实现删除
import java.util.ArrayList;
import java.util.Iterator;
public class MyCollectonDemo5 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
if("b".equals(s)){
//指向谁,那么此时就删除谁
it.remove();
}
}
System.out.println(list);
}
}
3、增强for
- 增强for介绍:是JDK5之后出现的,其内部原理是一个Iterator迭代器,简化数组和Collection集合的遍历
- 使用限制:实现Iterable接口的类才可以使用迭代器和增强for
import java.util.ArrayList;
public class MyCollectonDemo6 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
//1,数据类型一定是集合或者数组中元素的类型
//2,str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素
//3,list就是要遍历的集合或者数组
for(String str : list){
System.out.println(str);
}
}
}
- 增强for中修改第三方变量的值不会修改集合中的元素
import java.util.ArrayList;
public class MyCollectonDemo7 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for(String str : list){
str = "q";
System.out.println(str);
}
for (String s : list) {
System.out.println(s);
}//[a,b,c,d]
//System.out.println(list);
}
}
-
三种循环的使用场景
- 如果需要操作索引,使用普通for循环
- 如果在遍历的过程中需要删除元素,使用迭代器
- 如果仅仅想遍历,那么使用增强for
-
案例:Collection集合存储学生对象并遍历
//Student
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//GET...SET...
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//测试类
import java.util.ArrayList;
import java.util.Iterator;
public class MyCollectonDemo8 {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student s1 = new Student("小皮同学",23);
Student s2 = new Student("小路同学",31);
Student s3 = new Student("小贾同学",33);
list.add(s1);
list.add(s2);
list.add(s3);
//迭代器的方式进行遍历
Iterator<Student> it = list.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s);
}
System.out.println("-------------------------");
//增强for
for (Student student : list) {
System.out.println(student);
}
}
}
三、List集合
1、List集合基础
- List集合的概述:
- 有序集合,这里的有序指的是存取顺序
- 用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,List允许重复的元素
- List集合的特点:存取有序、可以重复、有索引
- List集合的特有方法
方法名 | 描述 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
import java.util.ArrayList;
import java.util.List;
public class MyListDemo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//method1(list);
//method2(list);
//method3(list);
//method4(list);
}
private static void method4(List<String> list) {
// E get(int index) 返回指定索引处的元素
String s = list.get(0);
System.out.println(s);
}
private static void method3(List<String> list) {
// E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
//被替换的那个元素,在集合中就不存在了.
String result = list.set(0, "qqq");
System.out.println(result);
System.out.println(list);
}
private static void method2(List<String> list) {
// E remove(int index) 删除指定索引处的元素,返回被删除的元素
//在List集合中有两个删除的方法
//第一个 删除指定的元素,返回值表示当前元素是否删除成功
//第二个 删除指定索引的元素,返回值表示实际删除的元素
String s = list.remove(0);
System.out.println(s);
System.out.println(list);
}
private static void method1(List<String> list) {
// void add(int index,E element) 在此集合中的指定位置插入指定的元素
//原来位置上的元素往后挪一个索引.
list.add(0,"qqq");
System.out.println(list);
}
}
2、数据结构
- 栈结构:先进后出
- 队列结构:先进先出
- 数组结构:查询快、增删慢
- 查询数据通过地址值和索引定位,查询任意数据耗时相同,查询速度快
- 删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
- 添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低
- 链表:查询慢、增删快
- 链表查询数据是否存在,必须从head开始查询
- 查询第N个数据,也是必须从head开始查询
3、List集合的实现类
- ArrayList底层实现:底层是数组结构实现,查询快、增删慢
- LinkedList底层实现:底层是链表结构实现(双向链表),查询慢、增删快
- ArrayList第一次添加元素的源码解析
-
LinkedList集合的特有功能
方法名 说明 public void addFirst(E e) 在该列表开头插入指定的元素 public void addLast(E e) 将指定的元素追加到此列表的末尾 public E getFirst() 返回此列表中的第一个元素 public E getLast() 返回此列表中的最后一个元素 public E removeFirst() 从此列表中删除并返回第一个元素 public E removeLast() 从此列表中删除并返回最后一个元素
import java.util.LinkedList;
public class MyLinkedListDemo4 {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//method1(list);
//method2(list);
//method3(list);
//method4(list);
}
private static void method4(LinkedList<String> list) {
String first = list.removeFirst();
System.out.println(first);
String last = list.removeLast();
System.out.println(last);
System.out.println(list);
}
private static void method3(LinkedList<String> list) {
String first = list.getFirst();
String last = list.getLast();
System.out.println(first);
System.out.println(last);
}
private static void method2(LinkedList<String> list) {
list.addLast("www");
System.out.println(list);
}
private static void method1(LinkedList<String> list) {
list.addFirst("qqq");
System.out.println(list);
}
}
- LinkedList添加元素源码解析
四、泛型
- 泛型的介绍:泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制
- 泛型的好处:
- 把运行时期的问题提前到了编译期间
- 避免了强制类型转换
- 泛型可以使用的地方
- 类后面 -> 泛型类
- 方法声明上 -> 泛型方法
- 接口后面 -> 泛型接口
- 什么是泛型类
- 一个类后面有,表示这个类是一个泛型类
- 创建泛型类对象时,必须要给这个泛型确定具体的数据类型
- 泛型的定义格式
- <类型>:指定一种类型的格式,尖括号里面可以任意书写,一般只写一个字母。例如:
- <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。例如: <E,T> <K,V>
泛型类
//就是一个泛型类
public class Box<E> {
private E element;
public E getElement() {
return element;
}
public void setElement(E element) {
this.element = element;
}
}
测试类
/**
* 自定义泛型类
*/
public class MyGenericityClass {
public static void main(String[] args) {
Box<String> box1 = new Box<>();
box1.setElement("给小丽的土味情话");
String element1 = box1.getElement();
System.out.println(element1);
Box<Integer> box2 = new Box<>();
box2.setElement(19);
Integer element2 = box2.getElement();
System.out.println(element2);
}
}
- 泛型方法使用
import java.util.ArrayList;
import java.util.Arrays;
/**
* 使用Java中的泛型方法
*/
public class GenericityMethod1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("给小花同学的土味情话");
list.add("给小丽同学的土味情话");
list.add("给小路同学的土味情话");
//将list集合转成一个数组并返回
//如果是空参的,那么返回的数组类型为Object类型的.
Object[] objects = list.toArray();
System.out.println(Arrays.toString(objects));
String[] strings = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(strings));
}
}
- 自定义泛型方法
- 格式:
修饰符 <类型> 返回值类型 方法名(类型 变量名) { }
->public <T> void show(T t) { }
- 泛型方法的T类型是在运行的时候确定的类型
- 格式:
/**
* 自定义泛型方法
* 定义一个泛型方法,传递一个集合和四个元素,将元素添加到集合中并返回
*/
public class GenericityMethod2 {
public static void main(String[] args) {
ArrayList<String> list1 = addElement(new ArrayList<String>(), "a", "b", "c", "d");
System.out.println(list1);
ArrayList<Integer> list2 = addElement(new ArrayList<Integer>(), 1, 2, 3, 4);
System.out.println(list2);
}
public static <T> ArrayList<T> addElement(ArrayList<T> list , T t1 ,T t2 ,T t3 ,T t4){
list.add(t1);
list.add(t2);
list.add(t3);
list.add(t4);
return list;
}
}
- 泛型接口定义格式:
修饰符 interface 接口名<类型> { }
- 泛型接口实现类1:定义实现类时,定义和接口相同泛型,创建实现类对象时明确泛型的具体类型
- 泛型接口实现类2:定义实现类时,直接明确泛型的具体类型
public class GenericityInterface {
public static void main(String[] args) {
GenericityImpl1<String> genericity = new GenericityImpl1<>();
genericity.method("小丽给我的土味情话");
GenericityImpl2 genericityImpl2 = new GenericityImpl2();
genericityImpl2.method(19);
}
}
interface Genericity<E>{
public abstract void method(E e);
}
class GenericityImpl2 implements Genericity<Integer>{
@Override
public void method(Integer integer) {
System.out.println(integer);
}
}
class GenericityImpl1<E> implements Genericity<E>{
@Override
public void method(E e) {
System.out.println(e);
}
}
- 类型通配符:<?>
- ArrayList<?>: 表示元素类型未知的ArrayList,它的元素可以匹配任何的类型;但是并不能把元素添加到ArrayList中了,获取出来的也是父类类型
- 类型通配符上限:<? extends 类型>
- ArrayListList <? extends Number>: 它表示的类型是Number或者其子类型
- 类型通配符下限: <? super 类型>
- ArrayListList <? super Number>: 它表示的类型是Number或者其父类型
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<Number> list2 = new ArrayList<>();
ArrayList<Object> list3 = new ArrayList<>();
printList(list1);
printList(list2);
method1(list1);
method1(list2);
//method1(list3);// 错误
//method2(list1);// 错误
method2(list2);
method2(list3);
}
private static void printList(ArrayList<?> list){}
//表示传递进来集合的类型,可以是Number类型,也可以是Number所有的子类类型
private static void method1(ArrayList<? extends Number> list){}
//表示传递进来集合的类型,可以是Number类型,也可以是Number所有的父类类型
private static void method2(ArrayList<? super Number> list){}
}