对象数组
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
public class Main {
public static void main(String[] args) {
Student[] Students = new Student[5];
Student s = new Student("张飞", 25);
Student s2 = new Student("关羽", 28);
Student s3 = new Student("赵云", 25);
Student s4 = new Student("黄忠", 30);
Student s5 = new Student("马超", 25);
Students[0] = s;
Students[1] = s2;
Students[2] = s3;
Students[3] = s4;
Students[4] = s5;
for (int i = 0; i < Students.length; i++) {
System.out.println(Students[i].getName()+"---"+Students[i].getAge());
}
}
}
---------------------------------------------------------------------------
张飞---25
关羽---28
赵云---25
黄忠---30
马超---25
集合的由来:
为了方便对多个对象进行操作,必须对多个对象进行存储。多个对象进行存储可以选择对象数组;因数组长度是固定的,对象数组不能适应变化的需求,为了适应变化的需求,Java提供集合类。
数组和集合的区别
A、长度区别
数组的长度固定
集合的长度可变
B、内容不同
数组存储的是同一种类型的元素
而集合可以存储不同类型的元素
C、元素的数据类型问题
数组可以存储基本数据类型,也可以存储引用数据类型
集合只能存储引用类型
集合类特点
集合只能用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
Collection:是集合的顶层接口,它的子体系有重复的,有唯一的,有有序的,有无序的。
Collection的功能概述:
1、添加功能
boolean add(Object obj):添加一个元素(通过ArrayList类进行实例话,永远返回true,永远添加成功即允许有重复的)
boolean addAll(Collection c):添加一个集合的元素(类似于add(Object obj)方法)
2、删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c): 移除一个集合的元素(只要有一个被移除,就返回true,即移除成功)
3、修改功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(只有包含集合中所有的元素才是包含,否则为false)
boolean isEmpty(): 判断集合是否为空
4、获取功能
Iterator iterator():迭代器,集合的专用遍历方式
Iterator接口中方法:
Object next():获取元素,并移动到下一位置。
boolean hasNext():如果仍有元素可以迭代,则返回true。
5、长度功能
int size():元素的个数
6、交集功能
boolean retainAll(Collection c):(集合A对集合B做交集,最终结果保存在A中,B不变。返回值表示为A是否发生过改变,true为A发生改变,false为不改变)
7、把集合转换为数组
Object[] toArray()
import java.util.ArrayList;
import java.util.Collection;
public class Main {
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
Student[] Students = new Student[5];
Student s = new Student("张飞", 25);
Student s2 = new Student("关羽", 28);
Student s3 = new Student("赵云", 25);
Student s4 = new Student("黄忠", 30);
Student s5 = new Student("马超", 25);
//把学生添加到集合
c.add(s);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
//把集合转成数组
Object[] objt = c.toArray();
for(int i = 0;i<objt.length;i++) {
Student ss = (Student) objt[i];
System.out.println(ss.getName()+"---"+ss.getAge());
}
}
}
---------------------------------------------------------------------------------------------
张飞---25
关羽---28
赵云---25
黄忠---30
马超---25
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator it = c.iterator();
while(it.hasNext()) {
String s = (String) it.next();
System.out.println(s+"----"+s.length());
}
}
}
-----------------------------------------------------------------------------------
hello----5
world----5
java----4
集合的使用步骤:
A:创建集合对象
B:创建元素对象
C:把元素添加到集合
D:遍历集合
a:通过集合对象获取迭代器对象
b:通过迭代器对象的hasNext()方法判断是否有元素
c:通过迭代器对象的next()方法获取元素并移动到下一位置
迭代器为什么不定义为一个类,而是一个接口?
由于Java中提供了很多的集合类,而这些集合类的数据方法不同,所以存储的方式和遍历的方式应该也不同,进而它们的遍历方式也应该不一样。最终没有定义迭代器类。集合都应该具备获取元素的操作,判断功能和获取功能应该是一个集合遍历所具备的,而每种集合的方式不同。所以把这两个功能提取出来并不提供实现,这种方式就是接口。
真正的具体实现类在哪里?
在真正的具体的子类中,以内部类的方式体现的。
迭代器源码:
public interface Iterator<E> {
boolean hasNext();
E next();
}
public interface Iterable<T> {
Iterator<T> iterator();
}
public interface Collection<E> extends Iterable<E> {
Iterator<E> iterator();
}
public interface List<E> extends Collection<E> {
Iterator<E> iterator();
}
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
public boolean hasNext() {}
public E next() {}
}
}
List接口概述
有序的Collection(也称为序列)。此接口的用户可以对列表中的每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。(与set不同,列表通常允许重复的元素。)
List集合的特有功能:
A:添加功能
void add(int index, Object element):在指定位置添加元素
B:获取功能
Object get(int index):获取指定位置的元素
List集合的特有遍历功能:
size()和get()方法结合。
C:列表迭代器
ListIterator listIterator():List集合特有的迭代器
该迭代器继承了Iterator迭代器,所以,就可以直接使用hasNext()和next()方法。
特有功能:
Object previous():获取上一个元素
boolean hasPrevious():判断是否有元素
注意:ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以一般无意义,不使用。
D:删除功能
Object remove(int index):根据索引删除元素,返回被删除的元素
E:修改功能
Object set(int index, Object element):根据索引修改元素,返回被修改的元素
问题:判断集合中是否有"world"元素,若有,添加"javaee"元素。
ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
产生原因:
迭代器是依赖于集合而存在的,在判断成功后,集合中新添加了元素,而迭代器却不知道,所以报错,这种错误叫并发修改异常。
问题描述为:迭代器遍历元素的时候,通过集合是不能修改元素的。
解决方法:
A:迭代器迭代元素,迭代器修改元素
新加元素是跟在刚才判断迭代的元素后面。
B:集合遍历元素,集合修改元素(普通for)
新加元素在集合最后添加
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class IteratorDemo2 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
//迭代器遍历
//报错:ConcurrentModificationException
// Iterator it = list.iterator();
// while(it.hasNext()) {
// String s = (String) it.next();
// if("world".equals(s)) {
// list.add("javaee");
// }
// }
//方式A:迭代器迭代元素,迭代器修改元素
//而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
// ListIterator lit = list.listIterator();
// while (lit.hasNext()) {
// String s = (String) lit.next();
// if ("world".equals(s)) {
// lit.add("javaee");
// }
// }
// System.out.println("list:"+list);
//list:[hello, world, javaee, java]
//方式B:集合遍历元素,集合修改元素(普通for)
for(int x=0;x<list.size();x++) {
String s = (String) list.get(x);
if("world".equals(s)) {
list.add("javaee");
}
}
System.out.println("list:"+list);
//list:[hello, world, java, javaee]
}
}
List的子类特点:
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
去除集合中重复的字符串的重复值两种方法:
import java.util.ArrayList;
import java.util.Iterator;
//去除集合中重复的字符串的重复值
public class ArrayListDemo {
public static void main(String[] args) {
//创建集合对象
ArrayList array = new ArrayList();
//添加多个字符串元素(包含内容相同的)
array.add("hello");
array.add("world");
array.add("java");
array.add("world");
array.add("java");
array.add("world");
array.add("java");
array.add("java");
array.add("java");
array.add("world");
array.add("world");
array.add("java");
array.add("java");
//方法1:创建新集合,遍历旧集合新集合中没有的加入到旧集合中
ArrayList newarray = new ArrayList();
Iterator it = array.iterator();
while(it.hasNext()) {
String s = (String) it.next();
if(!newarray.contains(s)) {
newarray.add(s);
}
}
//遍历新集合
for(int i=0; i<newarray.size(); i++) {
String s= (String) newarray.get(i);
System.out.println(s);
}
// hello
// world
// java
//方法2:双重循环在原集合中去除重复元素
for(int i=1; i<array.size(); i++) {
for(int j=0; j<i;j++) {
if(array.get(i).equals(array.get(j))) {
array.remove(i);
i--;
break;
}
}
}
for(int i=0; i<array.size(); i++) {
String s= (String) array.get(i);
System.out.println(s);
}
// hello
// world
// java
}
}
注意:contains()方法的底层依赖的是equals()方法。所以Student类重写equals()方法。
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo2 {
public static void main(String[] args) {
// 创建集合对象
ArrayList array = new ArrayList();
// 创建学生对象
Student s1 = new Student("关羽", 25);
Student s2 = new Student("张飞", 27);
Student s3 = new Student("赵云", 24);
Student s4 = new Student("马超", 26);
Student s5 = new Student("黄忠", 30);
Student s6 = new Student("赵云", 22);
Student s7 = new Student("马超", 26);
Student s8 = new Student("黄忠", 30);
Student s9 = new Student("关羽", 28);
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);
array.add(s5);
array.add(s6);
array.add(s7);
array.add(s8);
array.add(s9);
//创建新集合
ArrayList newArray = new ArrayList();
//遍历旧集合,获取得到每一个元素
Iterator it = array.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
if(!newArray.contains(s)) {
newArray.add(s);
}
}
//遍历新集合
for(int x = 0; x< newArray.size();x++) {
Student s = (Student) newArray.get(x);
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
-----------------------------------------------------------------
关羽---25
张飞---27
赵云---24
马超---26
黄忠---30
赵云---22
关羽---28
泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。
格式:
<数据类型>
此处的数据类型只能是引用类型。
好处:
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线
泛型使用位置:
看API,如果类,接口,抽象类后面跟的有<E>就说要使用泛型。一般来说就是在集合中使用。
泛型由来
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型的转换的问题。也就存在着隐患,所以Java提供了泛型来解决这个安全问题。
泛型应用
泛型类
把泛型定义在类上
格式:public class 类名<泛型类型1,泛型类型2,....>
注意:泛型类型必须是引用类型
泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型)
泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1,....>
泛型高级(通配符)
泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向下限定,E及其子类
? super E
向上限定,E及其父类
import java.util.ArrayList;
import java.util.Iterator;
//去除集合中重复的字符串的重复值
public class ArrayListDemo {
public static void main(String[] args) {
// 创建集合对象
ArrayList<String> array = new ArrayList<String>();
// 添加多个字符串元素(包含内容相同的)
array.add("hello");
array.add("world");
array.add("java");
array.add("world");
array.add("java");
array.add("world");
array.add("java");
array.add("java");
array.add("java");
array.add("world");
array.add("world");
array.add("java");
array.add("java");
// 方法1:创建新集合,遍历旧集合新集合中没有的加入到旧集合中
ArrayList<String> newarray = new ArrayList<String>();
Iterator<String> it = array.iterator();
while (it.hasNext()) {
String s = it.next();
if (!newarray.contains(s)) {
newarray.add(s);
}
}
// 遍历新集合
for (int i = 0; i < newarray.size(); i++) {
String s = newarray.get(i);
System.out.println(s);
}
// hello
// world
// java
// 方法2:双重循环在原集合中去除重复元素
for (int i = 1; i < array.size(); i++) {
for (int j = 0; j < i; j++) {
if (array.get(i).equals(array.get(j))) {
array.remove(i);
i--;
break;
}
}
}
for (int i = 0; i < array.size(); i++) {
String s = array.get(i);
System.out.println(s);
}
// hello
// world
// java
}
}
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo2 {
public static void main(String[] args) {
// 创建集合对象
ArrayList<Student> array = new ArrayList<Student>();
// 创建学生对象
Student s1 = new Student("关羽", 25);
Student s2 = new Student("张飞", 27);
Student s3 = new Student("赵云", 24);
Student s4 = new Student("马超", 26);
Student s5 = new Student("黄忠", 30);
Student s6 = new Student("赵云", 22);
Student s7 = new Student("马超", 26);
Student s8 = new Student("黄忠", 30);
Student s9 = new Student("关羽", 28);
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);
array.add(s5);
array.add(s6);
array.add(s7);
array.add(s8);
array.add(s9);
//创建新集合
ArrayList<Student> newArray = new ArrayList<Student>();
//遍历旧集合,获取得到每一个元素
Iterator<Student> it = array.iterator();
while (it.hasNext()) {
Student s = it.next();
if(!newArray.contains(s)) {
newArray.add(s);
}
}
//遍历新集合
for(int x = 0; x< newArray.size();x++) {
Student s = (Student) newArray.get(x);
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
增强for:是for循环的一种
格式:
for(元素数据类型 变量:数组或者Collection集合){
使用变量即可,该变量就是元素
}
嵌套集合
import java.util.ArrayList;
public class ArrayListDemo3 {
public static void main(String[] args) {
// 创建班级集合
ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>();
// 创建第一个学生集合
ArrayList<Student> firstArrayList = new ArrayList<Student>();
// 创建学生对象
Student s1 = new Student("唐僧", 30);
Student s2 = new Student("孙悟空", 29);
Student s3 = new Student("猪八戒", 28);
Student s4 = new Student("沙僧", 27);
Student s5 = new Student("白龙马", 26);
firstArrayList.add(s1);
firstArrayList.add(s2);
firstArrayList.add(s3);
firstArrayList.add(s4);
firstArrayList.add(s5);
bigArrayList.add(firstArrayList);
// 创建第二个学生集合
ArrayList<Student> secondArrayList = new ArrayList<Student>();
// 创建学生对象
Student s11 = new Student("诸葛亮", 30);
Student s22 = new Student("司马懿", 28);
Student s33 = new Student("周瑜", 26);
secondArrayList.add(s11);
secondArrayList.add(s22);
secondArrayList.add(s33);
bigArrayList.add(secondArrayList);
// 创建第二个学生集合
ArrayList<Student> thirdArrayList = new ArrayList<Student>();
// 创建学生对象
Student s111 = new Student("宋江", 40);
Student s222 = new Student("吴用", 35);
Student s333 = new Student("高俅", 30);
Student s444 = new Student("李师师", 22);
thirdArrayList.add(s111);
thirdArrayList.add(s222);
thirdArrayList.add(s333);
thirdArrayList.add(s444);
bigArrayList.add(thirdArrayList);
//遍历
for(ArrayList<Student> array : bigArrayList) {
for(Student s : array) {
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("----------------");
}
}
}
----------------------------------------------------------------------------------------------
唐僧---30
孙悟空---29
猪八戒---28
沙僧---27
白龙马---26
----------------
诸葛亮---30
司马懿---28
周瑜---26
----------------
宋江---40
吴用---35
高俅---30
李师师---22
----------------
可变参数概述:
定义方法的时候不知道该定义多少个参数
格式:
修饰符 返回值类型 方法名(数据类型... 变量名){}
注意:
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
Arrays工具类中的一个方法
public static <T> List<T> asList(T... a)