文章目录
- JAVA集合
- 对象数组
- JAVA集合概述:
- Collection集合的功能概述:
- JAVA集合——list类
- List概述及特点
- List的遍历:(案例)
- ListIterator的特有功能:
- List的三个子类的特点:
- 并发修改异常产生的原因及解决方案
- 数据结构的理解与特性
- JAVA集合——ArrayList
- ArrayList存储与遍历
- 案例:(去除ArrayList中的重复数值)
- Java集合——Vector
- Vector的概述:
- Vector类特有功能:
- JAVA集合——LinkedList
- LinkedList概述:
- LinkedList特有的功能:
- LinkedList案例:(模拟栈的数据结构)
- JAVA泛型:
- 概述和基本使用:
- 泛型的好处的演示:(自定义类中使用泛型!)
- 多泛型的使用:
- 泛型接口的概述和使用
- 泛型在方法上的使用:
- 泛型高级之通配符:
- 增强for循环:
- JAVA可变参数:
- Arrays工具类的asList()方法的使用:
- JAVA 嵌套集合:(ArrayList嵌套ArrayList)
JAVA集合
对象数组
- 案例:
需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。 - 代码示例:(Student类定义)
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
= name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}- 代码示例:(主函数示例:)
public class MyTest {
public static void main(String[] args) {
//需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
// 学生:Student
// 成员变量:name,age
// 构造方法:无参,带参
// 成员方法:getXxx()/setXxx()
// 存储学生的数组?自己想想应该是什么样子的?
Student s1 = new Student("苏沅湘", 20);
Student s2 = new Student("崔季宣", 20);
Student s3 = new Student("周颖", 18);
//把要把上面三个学生对象存储起来
//创建对象数组
Student[] students={s1,s2,s3};
//遍历对象数组
for (int i = 0; i < students.length; i++) {
Student student = students[i];
System.out.println(student.getName()+"==="+student.getAge());
}
//删掉数组中的第三个元素
Student[] students1 = Arrays.copyOf(students, 2);
System.out.println(Arrays.toString(students1));
}
}
----------------------
输出:
苏沅湘===20
崔季宣===20
周颖===18
[org.westos.demo.Student@1b6d3586, org.westos.demo.Student@4554617c]- 根据以上案例可以得到的结论:
a. 数组作为容器:可以存储多种多样的类型,但是数组作为容器,增删数组中的元素是很不方便的。
b. 正因为如此,那Java为了我们更方便的去操作(增删改查)容器中的元素,给我们提供了另外一个容器,叫做集合
JAVA集合概述:
- 概念:
Java为了我们更方便的去操作(增删改查)容器中的元素(数组的操作有弊端!),给我们提供了另外一个容器,叫做集合。
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。 - 数组和集合的区别:
数组:可以存储基本数据类型,也可以存储引用数据类型。
集合:只能存储引用数据类型
数组:一定定义,长度不可变
集合:长度是可变的。
数组:只能存储同一种数据类型
集合:可以存储多种数据类型 - JAVA中由很多类型的集合,具体可以参考**“Collection集合的继承体系:”**

Collection集合的功能概述:
- Collection 接口 是个单列集合的父类:
示例:
public class MyTest {
public static void main(String[] args) {
// Collection 接口 是个单列集合的父类
//多态(重点),从继承图中可知:ArrayList是Collection的子类!
Collection collection = new ArrayList();
//往集合中添加元素,返回值的意思是 是否添加成功
boolean b = collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
System.out.println(collection);
}
}
--------------
输出:
[aaa, bbb, ccc]- 具体的集合功能可以通过查看API说明手册看到,以下只一部分常用的举例:
- 功能示例:
a. 添加功能
boolean add(Object obj): 添加一个元素(返回的是是否成功)
boolean addAll(Collection c): 添加一个集合的元素 (给一个集合添加进另一个集合中的所有元素)
---------------------
示例:
Collection collection1 = new ArrayList();
collection1.add(100); //自动装箱
collection1.add(Integer.valueOf(20));
collection1.add(300);
collection1.add(400);
//删掉集合中的元素
boolean b = collection1.remove(400);
System.out.println(collection1);
//清空集合中集合中的元素
collection1.clear();
System.out.println(collection1);
输出:
[aaa, bbb, ccc, 100, 20, 300, 400]
[100, 20, 300, 400]- b. 删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素,如果没有交集元素 则删除失败 返回false
------------------------
示例1:
Collection collection1 = new ArrayList();
collection1.add(100); //自动装箱(因为集合中存储的是引用类型!,所以自动装箱成Integer类型的数据!)
collection1.add(Integer.valueOf(20));//手动装箱
collection1.add(300);
collection1.add(400);
//删掉集合中的元素
boolean b = collection1.remove(400);
System.out.println(collection1);
//清空集合中集合中的元素
collection1.clear();
System.out.println(collection1);
输出:
[100, 20, 300]
[]
-------------------
示例2:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(2000);
collection1.add(500);
Collection collection2 = new ArrayList();
collection2.add(100); //自动装箱
collection2.add(400);
//A集合removeAll(B集合) A 集合会移除掉两个集合的交集元素,如果移除了返回true,没有交集元素返回false
boolean b = collection1.removeAll(collection2);
System.out.println(b);
System.out.println(collection1);
System.out.println(collection2);
输出:
false
[1000, 2000, 500]
[100, 400]- c. 判断功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合包含另一个集合中所有的元素才算包含 才返回true),比如:1,2,3 containsAll 12=true 1,2,3 containsAll 2,3,4=false。
boolean isEmpty():判断集合是否为空
--------------------------
示例1:
//与判断相关的方法
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(4000);
collection1.add(500);
//判断集合中是否有这个元素
boolean b = collection1.contains(500);
System.out.println(b);
输出:
true
------------------------
示例2:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(500);
//获取集合的长度
int size = collection1.size();
System.out.println(size);
collection1.clear();
//判断一个集合是否为空
boolean empty = collection1.isEmpty();
System.out.println(empty);
//"".isEmpty(); 字符串也有一个判断是否为空的方法!- d. 获取功能:集合只能通过迭代器进行迭代!
Iterator<E> iterator()(重点)
-----------------------
示例:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(2000);
collection1.add(3000);
collection1.add(4000);
collection1.add(4000);
collection1.add(500);
//遍历Collection集合需要获取一个迭代器
//对 collection 进行迭代的迭代器
/* boolean hasNext ()
如果仍有元素可以迭代,则返回 true。
E next ()
返回迭代的下一个元素。*/
// 接口 Iterator<E >
Iterator iterator = collection1.iterator();
//java.util.ArrayList$Itr @ 1 b6d3586
Object next = iterator.next();//手动移动
System.out.println(next);
System.out.println(iterator);
while (iterator.hasNext()){
Object obj= iterator.next();
System.out.println(obj);
}
System.out.println(collection1);
输出:
1000
java.util.ArrayList$Itr@1b6d3586(这个iterator是一个内部类的对象!(通过打印地址值发现!,但通过追踪源码我无法得出此结论!))
定义为内部类的好处:可以直接访问集合中的对象!(内部类可以访问外部类的信息!)
2000
3000
4000
4000
500
[1000, 2000, 3000, 4000, 4000, 500] (说明迭代器进行迭代的时候,只是迭代指针发生了变化,而集合本身并没有发生滨化!)
----------------------------------
示例2:(Student类的定义在本文第一部分已经给出了)
Student s1 = new Student("苏沅湘", 20);
Student s2 = new Student("崔季宣", 20);
Student s3 = new Student("周颖", 18);
Collection collection = new ArrayList();
collection.add(s1);
collection.add(s2);
collection.add(s3);
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
//向下转型
Student student= (Student) next;
System.out.println(student.getName()+"==="+student.getAge());
}
-------------------------
输出:
苏沅湘===20
崔季宣===20
周颖===18- e. 长度功能
int size():元素的个数
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
回答:数组有,字符串有,集合没有(集合是size)。- f. 交集功能
例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化
boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
----------
示例:
//取两个集合的交集元素
Collection collection1 = new ArrayList();
collection1.add(100); //自动装箱
collection1.add(200);
collection1.add(300);
collection1.add(400);
collection1.add(4000);
collection1.add(500);
Collection collection2 = new ArrayList();
collection2.add(100); //自动装箱
collection2.add(200);
collection2.add(300);
collection2.add(400);
collection2.add(600);
//例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化 发生过变化返回true 没有发生变化返回false
boolean b = collection1.retainAll(collection2);
System.out.println(b);
System.out.println(collection1);
System.out.println(collection2);
输出:
true
[100, 200, 300, 400](collection1中只剩下了交集的元素)
[100, 200, 300, 400, 600](collection2的元素未发生变化)- g. 把集合转换为数组
Object[] toArray()
---------------
示例:
Collection collection1 = new ArrayList();
collection1.add(1000); //自动装箱
collection1.add(2000);
collection1.add(3000);
collection1.add(4000);
collection1.add(4000);
collection1.add(500);
把一个集合转换成数组(手动版:)
Integer[] integers = new Integer[collection1.size()];
Iterator iterator = collection1.iterator();
int i=0;
while (iterator.hasNext()){
Object next = iterator.next();
Integer integer= (Integer) next;
integers[i++]=integer;
}
System.out.println(Arrays.toString(integers));
toArray();把一个集合转换成数组(这个数组是Object型的)
Object[] objects = collection1.toArray();
//遍历途中可以对元素进行向下转型(必须向下转型才能获取相应的数值!)
for (int j = 0; j < objects.length; j++) {
Integer object = (Integer) objects[j];
System.out.println(object.intValue());
}
输出:
[1000, 2000, 3000, 4000, 4000, 500]
1000
2000
3000
4000
4000
500- IDEA小技巧:按住alt操作鼠标,多列选中,对多列同时进行操作!
JAVA集合——list类
List概述及特点
- List概述及特点: 元素有序,并且每一个元素都存在一个索引.元素可以重复.(这里的有序指的是:可以通过索引来获取元素!)
- List集合的特有功能概述:
void add(int index,E element): 在指定索引处添加元素
E remove(int index): 移除指定索引处的元素 返回的是移除的元素
E get(int index): 获取指定索引处的元素
E set(int index,E element): 更改指定索引处的元素 返回的而是被替换的元素- 根据元素查找索引:
int index = list.indexOf(100);
int index2 = list.lastIndexOf(100);- 遍历集合中的元素:(相当于创建了一个匿名内部类)
list.forEach(new Consumer()){
@Override
public void accept(Object o){
System.out.println(o);
}
}- 上面遍历的方法可以用Lambda进行简化表示:(简化上面匿名内部类的写法!)
//可以使用Lambda 简化上面的写法
System.out.println("===========================");
list.forEach((obj)->System.out.println(obj));List的遍历:(案例)
- 案例:List集合遍历(应该有三种方法:两种迭代器,一种for循环)
public class MyTest3 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1000); //自动装箱
list.add(2000);
list.add(3000);
list.add(4000);
list.add(4000);
list.add(500);
//遍历方式1: 利用Colletction的迭代器
//list.iterator()
//遍历方式2:List 有一个自己的迭代器
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object next = listIterator.next();
System.out.println(next);
}
System.out.println("==============================");
//遍历方式3 采用for循环遍历
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
System.out.println(o);
}
}
}
---------
输出:
1000
2000
3000
4000
4000
500
==============================
1000
2000
3000
4000
4000
500- 案例:List集合存储学生对象并遍历
public class MyTest4 {
public static void main(String[] args) {
Student s1 = new Student("苏沅湘", 20);
Student s2 = new Student("崔季宣", 20);
Student s3 = new Student("周颖", 18);
List arrayList = new ArrayList();
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
for (int i = 0; i < arrayList.size(); i++) {
Object o = arrayList.get(i);
Student student= (Student) o;
System.out.println(student.getName()+"==="+ student.getAge());
}
}
}
-------------
输出:
苏沅湘===20
崔季宣===20
周颖===18ListIterator的特有功能:
- 概念:ListIterator 继承自Iterator 可以使用Iterator中的方法
- ListIterator的特有功能:
boolean hasPrevious(): 是否存在前一个元素
E previous(): 返回列表中的前一个元素- 注意:
a. 以上两个方法组合可以实现反向遍历,但是注意:要完成反向遍历之前要先进行正向遍历 ,这样指针才能移到最后
b. 如果直接反向遍历是没有效果的 ,因为指针默认位置就在最前面 他前面没有元素。
List的三个子类的特点:
- List的三个子类的特点:
- ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。 - Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。 - LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
- List有三个子集合,我们到底使用谁呢?
要安全还是要效率?
是查找多还是增删多?
(根据以上特性来选择!)
并发修改异常产生的原因及解决方案
- 案例演示:(需求:我有一个集合,我想判断里面有没有 “world” 这个元素,如果有,我就添加一个 “javaee” 元素,请写代码实现。)
public class MyTest2 {
public static void main(String[] args) {
/* 需求:我有一个集合,请问,我想判断里面有没有 "world" 这个元素,
如果有,我就添加一个 "javaee" 元素,请写代码实现。*/
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("world");
方式1:
/* if (list.contains("world")) {
list.add("javaee");
}
System.out.println(list);
*/
方式2:
// ConcurrentModificationException 并发修改异常
//当你使用迭代器,对集合的元素,进行迭代,那么在迭代途中,先要增删集合中的元素,就会出现并发修改异常
//为什么?是因为,通过集合获取到,这个迭代器之后,迭代器,已经预先知道,集合中的元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,你突然要增删元素,就会打乱迭代器的迭代顺序,所以就会抛出并发修改异常
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()) {
Object next = listIterator.next();
String ele = (String) next;
if (ele.equals("world")) {
//list.add("javaee"); // 这样的写法会报错
// list.remove("aaa"); // 这样的写法会报错
listIterator.add("javaee");
}
}
System.out.println(list);
//方式3 使用for循环遍历
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("aaa")) {
list.add("vvvv");
}
}
System.out.println(list);
}
}- ConcurrentModificationException 并发修改异常:
当你使用迭代器,对集合元素,进行迭代,那么在迭代途中,如果要增删集合中的元素,就会出现冰法修改异常 - 原因:
因为,通过集合获取到这个迭代器之后,迭代器,已经预先知道,集合总的元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,你突然要增删元素,就会打乱迭代其的迭代顺序,所以就会抛出并发修改异常。 - 解决方式:
解决方式1:(如果使用迭代器遍历,那么在遍历途中,想要增删元素,那么你就使用迭代器自带的增删元素的方法)
解决方式2:使用for循环遍历
数据结构的理解与特性
- 数据结构概述及常见数据结构:
数据结构其实就是存储数据的格式
分类: 栈 , 队列 , 数组 , 链表 , 树 , 哈希表 - 栈特点: 先进后出
- 队列: 先进先出
- 数组特点: 查询快 , 增删慢
- 链表特点: 查询慢 , 增删快
JAVA集合——ArrayList
ArrayList存储与遍历
- JDK1.8新增的一个方法也能遍历集合
void forEach(Consumer<? super E> action) 执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常 - 其他遍历操作:
迭代器(因为ArrayList还是List的子类,可以利用Collection的迭代器或者List独有的迭代器)
普通for(因为ArrayList还是List的子类)- 示例:
public class MyTest {
public static void main(String[] args) {
//
ArrayList list = new ArrayList(); ArrayList指向(这次与以往不同,不是由Collection或者List指向它,利用多态进行访问了!)
/* int lastIndexOf (Object o)
返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 - 1。
int indexOf (Object o)
返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 - 1。
void forEach (Consumer < ? super E > action)
执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。*/
list.add(100);
list.add(200);
list.add(300);
list.add(100);
list.add(400);
list.add(500);
//根据元素查找改元素第一次出现的索引
int index = list.indexOf(100);
System.out.println(index);
int i = list.lastIndexOf(100);
System.out.println(i);
for (int i1 = 0; i1 < list.size(); i1++) {
System.out.println(list.get(i1));
}
System.out.println("===========================");
//Consumer
//遍历集合中的元素
list.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
//可以使用Lambda 简化上面的写法
System.out.println("===========================");
list.forEach((obj)->System.out.println(obj));
}
}案例:(去除ArrayList中的重复数值)
- 示例1:(不采取额外的存储结构)
public class MyTest2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(200);
list.add(100);
list.add(200);
list.add(100);
list.add(200);
list.add(100);
list.add(200);
list.add(300);
list.add(100);
list.add(400);
list.add(500);
list.add(100);
list.add(200);
list.add(300);
list.add(100);
list.add(400);
list.add(500);
list.add(100);
list.add(200);
list.add(100);
list.add(200);
//去除集合中的重复元素
//每次拿一个元素,跟后面的每个元素取比较,如果遇到相同的,就删除
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
/* Object o = list.get(i);
Object o1 = list.get(j)*/;
if(list.get(i).equals(list.get(j))){
list.remove(j);
j--;//记得 j--(重点!)
}
}
}
System.out.println(list);
// HashSet hashSet = new HashSet<>(list);
// System.out.println(hashSet);
}
}- 示例2:去除集合中字符串的重复值(可以采用辅助的数据结构)
public class MyTest {
public static void main(String[] args) {
/*A:
案例演示
需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
思路:创建新集合方式*/
ArrayList list = new ArrayList();
list.add("abc");
list.add("abc");
list.add("abc");
list.add("abc");
list.add("bbb");
list.add("abc");
list.add("ccc");
list.add("aaa");
ArrayList newList = new ArrayList();
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
if(!newList.contains(o)){
newList.add(o);
}
}
System.out.println(newList);
}
}
-------------
输出:
[abc, bbb, ccc, aaa]- 示例3:(去除自定义类对象的重复值,即:对象的成员变量值相同)
自定义学生类:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
= name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) { //必要的重写部分:
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, );
}
@Override
public int hashCode() { //非必要重写这部分!
return Objects.hash(name, age);
}
}- 主函数:
public class MyTest2 {
public static void main(String[] args) {
Student s1 = new Student("张三", 23);
Student s2 = new Student("张三", 23);
Student s3 = new Student("张三", 23);
Student s4 = new Student("张三2", 23);
Student s5 = new Student("张三3", 23);
ArrayList list = new ArrayList();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
ArrayList newList = new ArrayList();
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
if(!newList.contains(o)){ 重点在这里,为何它可以对比出不同对象是否是我们要删除的标准?
newList.add(o);
}
}
System.out.println("=============");
for (int i = 0; i < newList.size(); i++) {
Student stu = (Student) newList.get(i);
System.out.println(stu.getName()+"==="+stu.getAge());
}
}
}
-------------------
输出:
=============(这里刚好得到我们想要的结果!)
张三===23
张三2===23
张三3===23- 引出问题:contains()为何能知道我们比对的标准是什么?
追踪contains()源码可知:
在ArrayList.java文件下,得到:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
-------------------
进一步追踪,这里的indexOf()就是ArrayList.java下的indexOF()
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i])) 发现了重点:它会调用对象的equals()方法进行对比!(恰好我们在自定义的Student类中重写了equals()方法!,所以达到了我们想要的对比效果!)
return i;
}
return -1;
}Java集合——Vector
Vector的概述:
- 概述:Vector 类可以实现可增长的对象数组 , Vector 是同步的。
- 特点:Vector 底层数据结构是数组,查询快,增删慢,线程安全效率低
Vector类特有功能:
- 功能:
public void addElement(E obj) 添加元素的另一种方法
public E elementAt(int index) 获取元素的另一种方法
public Enumeration elements() 返回可迭代的迭代器- 案例演示:
public class MyTest {
public static void main(String[] args) {
//Vector 底层数据结构是数组,查询快,增删慢,线程安全效率低
/* public void addElement (E obj)
public E elementAt ( int index)
public Enumeration elements ()*/
Vector vector = new Vector();
vector.add(200);
vector.addElement(
300);
vector.add(200);
vector.addElement(300);
vector.add(200);
vector.addElement(300);
Object ox = vector.get(0);
Object o1 = vector.elementAt(0);
System.out.println(o1 == ox); 返回true,则说明这两种取元素的方法效果是一致的!
/*
lastElement()返回向量的最后一个组件。
firstElement()返回第一个组件(在指数 0项目)这个载体。
removeElement(Object obj)从该向量中移除第一个(最低索引)发生的参数。
void removeElementAt(int index)在指定的索引中删除组件。
setElementAt(E obj, int index)设置组件在指定的index这个向量是指定的对象。
*/
//遍历方法:
Enumeration elements = vector.elements();
while (elements.hasMoreElements()){
Object o = elements.nextElement();
System.out.println(o);
}
}
}
----------------
输出:
true
200
300
200
300
200
300JAVA集合——LinkedList
LinkedList概述:
- 概述:List 接口的链接列表实现 , 此实现不是同步的
- 特点:LinkedList 底层数据结构是链表,增删快查询慢,线程不安全效率高
LinkedList特有的功能:
- 功能:
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()- 特有功能示例:
public class MyTest {
public static void main(String[] args) {
//LinkedList 底层数据结构是链表,增删快查询慢,线程不安全效率高
/*
void addFirst(E e)在此列表的开始处插入指定的元素。
void addLast(E e)将指定的元素列表的结束。
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
*/
LinkedList linkedList = new LinkedList();
linkedList.addLast("eeee");
linkedList.add("aaa");
linkedList.addFirst("bbb");
linkedList.add("ccc");
System.out.println(linkedList);
Object o = linkedList.get(0);
System.out.println(o);
Object first = linkedList.getFirst();
System.out.println(first);
Object first2 = linkedList.getFirst();
System.out.println(first2);
System.out.println(linkedList);
}
}
-------------
输出:
[bbb, eeee, aaa, ccc]
bbb
bbb
bbb
[bbb, eeee, aaa, ccc]LinkedList案例:(模拟栈的数据结构)
- 示例:(自定义List类)
public class MyList {
LinkedList linkedList;
public MyList() {
linkedList= new LinkedList();
}
public void addObj(Object obj) {
linkedList.addFirst(obj);
}
public Object get() {
Object obj= linkedList.pop();
linkedList.addLast(obj); //这样做的目的是:操作完后,原来的数据还在!(但个人感觉好像挺没必要的!)
return obj;
}
}- 示例2:(主函数)
public class MyTest {
public static void main(String[] args) {
//需求:请用LinkedList模拟栈数据结构的集合,并测试
MyList myList = new MyList();
myList.addObj(100);
myList.addObj(200);
myList.addObj(300);
myList.addObj(400);
myList.addObj(500);
Object obj=myList.get();
System.out.println(obj);
obj = myList.get();
System.out.println(obj);
obj = myList.get();
System.out.println(obj);
obj = myList.get();
System.out.println(obj);
obj = myList.get();
System.out.println(obj);
System.out.println("==============");
obj = myList.get();
System.out.println(obj);
}
}
-----------------
输出:
500
400
300
200
100
==============
500(这里可以看到,当遍历完一回以后,数据元素没有发生变化!)JAVA泛型:
概述和基本使用:
- 泛型的由来:
ObjectTool
泛型的由来:通过Object转型问题引入
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
也就存在这隐患,所以Java提供了泛型来解决这个安全问题。 - 概念:
如果我们使用了泛型,就可以明确集合中到底放了什么样的数据类型。
泛型机制:是JDK1.5引入的,是一种将数据类型明确的工作,推迟到创建对象,或调用方法时,再去明确的一种机制。
也就是:参数化类型,把类型当作参数一样的传递。 - 定义方法:
泛型可以使用在类、接口 方法 <引用类型,引用类型>
------------------
例如:(在创建ArrayList对象的时候传入指定的泛型为:String,则ArrayList中只能存储这一种类型,若不传入:则默认为:Object类型,所以获取的时候,需要显示地进行向下转换!)
ArrayList<String> list1 = new ArrayList<Sring>()- 泛型的好处:
(1): 把运行时期的问题提前到了编译期间(这句话的含义不太懂?难道是指的避免了运行时候向下转换所造成的报错?这个编译器和运行期到底怎么解释的?编译器不行但是运行期可以(反射)?)
(2): 避免了强制类型转换
(3):优化了程序设计,解决了黄色警告线 - 集合明确了泛型的具体类型,那么这个集合就只能存储这种类型(避免向下转型)
示例:
示例:(避免向下转型)
查看上课所述!
//集合可以存储多种引用数据类型。
ArrayList list = new ArrayList();(这里没有专门指定泛型的类型声明,则默认为:Object)
list.add("abc");
list.add(200);
list.add(new StringBuffer());
Object o = list.get(0);
String str= (String) o;(向下转型)
int length = str.length();
-------------------------
//集合明确了泛型的具体类型,那么这个集合只能存储这种类型
ArrayList<String> list1 = new ArrayList<String>();
list1.add("abc");
list1.add("abc");
list1.add("abc");
String s = list1.get(0); //这里直接获取就OK,不需要向下转型泛型的好处的演示:(自定义类中使用泛型!)
- 一般通用类型的定义方法:(拥有扩展性,但是必须使用向下转型才能使用!)
public class MyClass {
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
----------------------------------------
public class MyTest {
public static void main(String[] args) {
//定义类时,或方法时,都想考虑这个扩展性
MyClass myClass = new MyClass();
myClass.setObj(100);
Object obj = myClass.getObj();
Integer integer= (Integer) obj; // 向下转型
MyClass myClass1 = new MyClass();
myClass1.setObj("abc");
Object obj1 = myClass1.getObj();
String string= (String) obj1;
}
}- 泛型定义方法:(既拥有了扩展性,同时也避免了向下转型!)
public class MyDem<T> { //T 泛型(在类中定义!)
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
-----------------------------
public class MyTest {
public static void main(String[] args) {
//设计一个类,既要扩展性,也不想向下转型。
//设计一个泛型类,给类加上泛型
//class A<T>{}
//泛型机制:是JDK1.5引入的,是一种将数据类型明确工作,推迟到创建对象,或调用方法时,再去明确的一种机制。
MyDem<String> myDem = new MyDem<>(); 由于前面已经声明了泛型的指代为:String,后面的<>中的泛型指定可以省略。
myDem.setObj("abc");
String obj = myDem.getObj();
System.out.println(obj);
//如不注明,则说明:泛型为Object!
MyDem<Integer> integerMyDem = new MyDem<>();
integerMyDem.setObj(200);
Integer obj1 = integerMyDem.getObj();
new ArrayList<Integer>(); //指明了ArrayList中泛型为:Integer,则ArrayList中只能存储Integer类型的数据。
}
}多泛型的使用:
- 示例:(定义泛型的类)
public class MyHaHa<R,P>{ //多泛型
private R r;
private P p;
}- 示例:(主函数)
public class MyTest {
public static void main(String[] args) {
MyHaHa<Integer, String> integerStringMyHaHa = new MyHaHa<>(); //多泛型的使用!
// integerStringMyHaHa.set("string");
ArrayList<Integer> integers = new ArrayList<>();
integers.add(100);
integers.add(100);
integers.add(100);
integers.add(100);
integers.add(100);
integers.add(100);
integers.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
}
}
----
输出:
100
100
100
100
100
100泛型接口的概述和使用
- 接口上的泛型都是在定义实现其子类的过程中传入的!
- 示例:(主函数中利用匿名内部类来实现接口的子类)
public class MyTest {
public static void main(String[] args) {
//泛型接口 什么时候去明确
//匿名内部类
new MyInterface<Integer,Integer>(){
@Override
public Integer set(Integer integer) {
return null;
}
};
}
}- 示例:(接口)
interface MyInterface<T,R>{ //在接口上使用泛型
R set(T t);
}- 示例:(实现接口的子类)
//子类在实现接口时,可以以明确接口上的泛型到底是什么类型
class Son implements MyInterface<String,Integer>{
@Override
public Integer set(String s) {
return null;
}
}泛型在方法上的使用:
- 示例:(自定义类)
class AA{
原来的办法:(为了考虑通用性)
/* public void set(Object str) {
System.out.println(str);
}*/
泛型方法
public<P> void set(P str) {
System.out.println(str);
}
}- 主函数:
public class MyTest {
public static void main(String[] args) {
//方法上的泛型,在你调用方法时,再去明确
AA aa = new AA();
aa.set(3.14); //这里没有专门指定泛型的语法,确也可以(神奇!!!!)
aa.set(200);
aa.set("abc");
}
}- 泛型一般在类和接口上使用的比较多!
泛型高级之通配符:
- 泛型通配符<?>:
任意类型,如果没有明确,那么就是Object以及任意的Java类了 - 泛型如果明确了数据类型以后,那么要求左右两边的数据类型必须一致
Collection<Object> col1 = new ArrayList<Object>() ;
Collection<Object> col2 = new ArrayList<Animal>() ; 报错(前后不一致)- 泛型统配符号:(前面用统配符号,后面则必须注明!)
ArrayList<?> objects2 = new ArrayList<cat>(); 这种方法就不需要前后都一致了!- ? extends E:向下限定,E及其子类
Collection<? extends Animal> col9 = new ArrayList<Object>() ; 报错(因为Object不是Animal的子类)
Collection<? extends Animal> col10 = new ArrayList<Animal>() ; 自己本身也可以
Collection<? extends Animal> col11 = new ArrayList<Dog>() ;- ? super E:向上限定,E及其父类
Collection<? super Animal> col13 = new ArrayList<Object>() ;
Collection<? super Animal> col14 = new ArrayList<Animal>() ;
Collection<? super Animal> col15 = new ArrayList<Dog>() ; 报错(因为Dog是Animal的子类而不是父类!)- 特别注意:泛型通配符的一些注意要点,这里面说明了这些泛型通配符在什么场景下使用,该如何使用,有哪些需要注意的坑!(非常重要!)
增强for循环:
- 概述:主要用来简化数组和Collection集合的遍历(在JDK1.5及以后版本适用)
- 格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}- 示例:(遍历数组)
int[] arr={20,20,30,80};
--------------------(普通for循环)
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
--------------------(增强for循环)
for(int i:arr){
System.out.println(arr[i]);
}- 示例:(遍历集合)
ArrayList<Integer> list = new ArrayList<>();
list.add(200);
list.add(200);
list.add(200);
list.add(200);
for(Integer num:list){
System.out.println(num);
}- 优点:简化了遍历的写法!
- 特点:它的底层是用迭代器在进行迭代,所以在迭代过程中不能进行增删元素!),这一点和Python极其像!
否则,就会报错:java.util.ConcurrentModificationException (并发修改异常!) - 普通for循环和增强for循环的适用特点:
a. 如果循环过程中需要拿索引做判断,那你就使用普通for循环
b. 如果只是遍历元素看一下,那就使用新式for循环
JAVA可变参数:
- 可变参数概述:
定义方法的时候不知道该定义多少个参数(如果也不知道具体类型的话,则可以使用泛型来进行指定!),可变参数(数组)中的数据类型都是一样的(是同属一个类型的数组!) - 格式:
修饰符 返回值类型 方法名(数据类型… 变量名){}- 注意:
a. 这里的变量其实是一个数组
b. 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个 - 示例:
public class MyTest {
public static void main(String[] args) {
int sum = add(1, 2);
int sum2 = add(1, 2, 3);
int sum3 = add(1, 2, 3, 4);
//可变参数:一次可以接收多个参数
System.out.println(sum);
System.out.println(sum2);
System.out.println(sum3);
}
//可变参数 数据类型 ... 参数名
//可变参数 本质是个数组
//如果说一个方法上,有普通参数,也有可变参数,可变参数肯定是最后一个参数
private static int add(int b,int... num) {
//System.out.println(num.length);
int sum=0;
for (int i : num) { // 增强for循环!
sum+=i;
}
return sum+b;
}
}Arrays工具类的asList()方法的使用:
- 概念:Arrays工具类的asList(T… t)方法的使用,将数组转换成集合。
- 格式:
static <T> List < T > asList(T...a)- 示例:
public class MyTest {
public static void main(String[] args) {
Integer[] integers = {20, 30, 50, 60};
如果你给该方法,传入的是一个引用类型数组,那么他会取出数组中的元素,放到集合中
List<Integer> integers1 = Arrays.asList(integers);
for (Integer integer : integers1) {
System.out.println(integer);
}
System.out.println("=====================================");
Integer[] integers2 = {20, 30, 50, 60};
Integer[] integers3 = {20, 30, 50, 60};
假如你传入两个以上的数组,他是把数组对象作为元素,放到集合中
List<Integer[]> integers4 = Arrays.asList(integers, integers2);
System.out.println(integers4);
Integer integer = integers4.get(0)[0];
System.out.println(integer);
System.out.println("================");
Integer[] integers5 = {20, 30, 50, 60};
List<Integer> integers6 = Arrays.asList(integers5);
int[] ints = {20, 30, 50, 60};
当你传人一个基本类型数组,那么转换成集合,集合放到是数组对象(数组对象的指针)
List<int[]> ints1 = Arrays.asList(ints);
int[] ints2 = ints1.get(0);
int[] ints3 = {20, 30, 50, 60};
int[] ints4 = {20, 30, 50, 60};
List<int[]> ints8 = Arrays.asList(ints3, ints4);
System.out.println(ints8);
List<Integer> integers7 = Arrays.asList(20, 30, 50, 30, 80); //自动装箱!
System.out.println(integers7);
}
}
------
输出:
20
30
50
60
=====================================
[[Ljava.lang.Integer;@1b6d3586, [Ljava.lang.Integer;@4554617c]
20(第0个元素)
================
[[I@74a14482, [I@1540e19d](List中存储的是int[]对象的地址值!)
[20, 30, 50, 30, 80]- 特别注意:得到的集合长度是不可变的。你不能往这个转换后的集合中添加元素(add)和删除元素(remove),只能获取元素(get)。
JAVA 嵌套集合:(ArrayList嵌套ArrayList)
- 示例:
public class MyTest3 {
public static void main(String[] args) {
ArrayList<Student> javaList = new ArrayList<>();
javaList.add(new Student("周丹", 19));
javaList.add(new Student("周颖", 19));
javaList.add(new Student("苏沅湘", 20));
javaList.add(new Student("崔继宣", 19));
ArrayList<Student> webList = new ArrayList<>();
webList.add(new Student("周丹1", 19));
webList.add(new Student("周颖1", 19));
webList.add(new Student("苏沅湘1", 20));
webList.add(new Student("崔继宣1", 19));
ArrayList<Student> linuxList = new ArrayList<>();
linuxList.add(new Student("周丹2", 19));
linuxList.add(new Student("周颖2", 19));
linuxList.add(new Student("苏沅湘2", 20));
linuxList.add(new Student("崔继宣2", 19));
//我站在西开的角度,我要存储这个三个班(嵌套ArrayList存储)
ArrayList<ArrayList<Student>> westosList = new ArrayList<>();
westosList.add(javaList);
westosList.add(webList);
westosList.add(linuxList);
//遍历每一个班的每一个学生的信息 二维集合的遍历
//普通for循环遍历
for (int i = 0; i < westosList.size(); i++) {
ArrayList<Student> minList = westosList.get(i);
// System.out.println(minList);
for (int j = 0; j < minList.size(); j++) {
Student student = minList.get(j);
System.out.println(student.getName() + "===" + student.getAge());
}
}
System.out.println("=================================");
//新式for循环遍历
for (ArrayList<Student> students : westosList) {
for (Student student : students) {
System.out.println(student.getName() + "===" + student.getAge());
}
}
System.out.println("======================");
}
}
---------------
输出:
周丹===19
周颖===19
苏沅湘===20
崔继宣===19
周丹1===19
周颖1===19
苏沅湘1===20
崔继宣1===19
周丹2===19
周颖2===19
苏沅湘2===20
崔继宣2===19
=================================
周丹===19
周颖===19
苏沅湘===20
崔继宣===19
周丹1===19
周颖1===19
苏沅湘1===20
崔继宣1===19
周丹2===19
周颖2===19
苏沅湘2===20
崔继宣2===19
======================
















