JAVA集合框架概述
集合框架涉及到的api
List接口是继承Collection接口,Set接口是继承Collection接口,
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
Collection接口中的常用方法
Collection接口中的常用方法代码测试1:CollectionTest
package com.atguigu.java2;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
/**
* 一、集合框架的概述
*
* 1.集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
* 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
*
* 2.1 数组在存储多个数据方面的特点:
* > 一旦初始化以后,其长度就确定了。
* > 数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。
* 比如:String[] arr;int[] arr1;Object[] arr2;
* 2.2 数组在存储多个数据方面的缺点:
* > 一旦初始化以后,其长度就不可修改。
* > 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
* > 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
* > 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
*
* 二、集合框架
* |----Collection接口:单列集合,用来存储一个一个的对象
* |----List接口:存储有序的、可重复的数据。 -->“动态”数组(不用考虑长度越不越界,超不超的问题)
* |----ArrayList、LinkedList、Vector
*
* |----Set接口:存储无序的、不可重复的数据 -->高中讲的“集合”
* |--Set接口三个主要的实现类--HashSet、LinkedHashSet、TreeSet
*
* |----Map接口:双列集合,用来存储一对(key - value)一对的数据 -->高中函数:y = f(x), value = f(key)
* |--Map接口几个实现类--HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
*
*
* 三、Collection接口中的方法的使用
*
*/
public class CollectionTest {
@Test
public void test1(){
Collection coll = new ArrayList();
//add(Object e):将元素e添加到集合coll中
coll.add("AA");
coll.add("BB");
coll.add(123);//自动装箱
coll.add(new Date());
//size():获取添加的元素的个数
System.out.println(coll.size());//4
//addAll(Collection coll1):将coll1集合中的元素添加到当前的集合中
Collection coll1 = new ArrayList();
coll1.add(456);
coll1.add("CC");
coll.addAll(coll1);
System.out.println(coll.size());//6
System.out.println(coll);//[AA, BB, 123, Sun Jan 30 23:17:11 CST 2022, 456, CC]
//clear():清空集合元素
coll.clear();
//isEmpty():判断当前集合是否为空
System.out.println(coll.isEmpty());//true //是空的
}
}
Collection接口中的常用方法代码测试2(下面的CollectionTest会用到 此Person类):
Person.java
package com.atguigu.java;
import java.util.Objects;
/**
* CollectionTest会用到 此Person类
*/
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
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 "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
System.out.println("调用了Person类的equals()方法");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
CollectionTest.java
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* Collection接口中声明的方法的测试
*
* 结论:
* 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals().
*
*/
public class CollectionTest {
@Test
public void test1(){
Collection coll = new ArrayList();
coll.add(123);//自动装包
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
// Person p=new Person("Jerry",20);
// coll.add(p);
// System.out.println(coll.contains(p));//true
coll.add(new Person("Jerry",20));
//1.contains(Object obj):判断当前集合中是否包含obj
//我们在判断时会调用obj对象所在类的equals()。
boolean contains = coll.contains(123);
System.out.println(contains);//true
System.out.println(coll.contains(new String("Tom")));//true 判断的是 是否有一样内容的 在里面,而不是比较地址
System.out.println(coll.contains(new Person("Jerry",20)));//contains内调的是当前传入对象的equals()
//false (Person类中默认没重写equals方法,而Object类的默认的equals方法是比较地址的 “=”) -->true(实际拿着这个contains的参数这个对象所在类的equals方法,
// 即new Person("Jerry",20)去 点equals(),
// 把集合中的数据依次放在equals的形参比较,一旦找到相同的就终止了,就不用往后去比了)
//2.containsAll(Collection coll1):判断形参coll1中的所有元素是否都存在于当前集合中,这里同上也是调用了 参数的equals()方法
Collection coll1 = Arrays.asList(123,4567);//
System.out.println(coll1);//[123, 4567]
System.out.println(coll.containsAll(coll1));// false ,有一个数据不在coll中
}
@Test
public void test2(){
//3.remove(Object obj):从当前集合中移除obj元素。
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
coll.remove(1234);//返回值boolean类型,表示是否移除,如果存在且移除成功就返回true,不存在就返回false
System.out.println(coll);//1234不存在,所以没有删除。
// [123, 456, Person{name='Jerry', age=20}, Tom, false]
coll.remove(new Person("Jerry",20));
System.out.println(coll);//因为重写了equals,所以这里移除了内容相同的元素。
//[123, 456, Tom, false]
//4. removeAll(Collection coll1):差集:从当前集合中移除coll1中所有的元素,也就是移除共有的
Collection coll1 = Arrays.asList(123,456);
coll.removeAll(coll1);//只能移除共有的。
System.out.println(coll);//[Tom, false]
}
@Test
public void test3(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
System.out.println(coll);//[123, 456, Person{name='Jerry', age=20}, Tom, false]
//6.equals(Object obj):要想返回true,需要当前集合和形参集合的元素都相同。
Collection coll2 = new ArrayList();
coll2.add(456);
coll2.add(123);
coll2.add(new Person("Jerry",20));
coll2.add(new String("Tom"));
coll2.add(false);
System.out.println(coll.equals(coll2));//false,因为ArrayList是有序的,coll是 123,456,而coll2是456,123,两个不是一个顺序,所以是false
//5.retainAll(Collection coll1):交集:获取当前集合和coll1集合的交集,并返回给当前集合
Collection coll1 = Arrays.asList(123,456,789);
coll.retainAll(coll1);//求交集 ,然后修改coll这个集合
System.out.println(coll);//[123, 456]
}
@Test
public void test4(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
//7.hashCode():返回当前对象的哈希值,这个方法在Object中有,所以任何对象都能调用这个求hashcode 的方法
System.out.println(coll.hashCode());//-1200490100
//8.集合 --转换为->数组:toArray()
//add()函数添加的是Object类型的元素,toArray()函数返回的是Object类型的数组
Object[] arr = coll.toArray();
for(int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
//123
//456
//Person{name='Jerry', age=20}
//Tom
//false
}
//拓展:数组 --->集合:调用Arrays类的静态方法asList()
//new String[]{"AA", "BB", "CC"}是一个String类型的数组,
//List是一个“动态数组”,与数组对标,所以这里返回类型是List
List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
System.out.println(list);//[AA, BB, CC]
//new int[]{123, 456}是int型数组
List arr1 = Arrays.asList(new int[]{123, 456});//new int[]{123, 456}这种写法会被asList()方法认为是一个元素
System.out.println(arr1);//[[I@3d82c5f3] 这是一个 元素,这个元素是一维数组(由左边第二个[可知是一维数组,由左边第三个I知是int类型)的地址
System.out.println(arr1.size());//1
List arr2 = Arrays.asList(new Integer[]{123, 456});//new Integer[]{123, 456} 这种写法会被认为是多个元素
System.out.println(arr2 );//[123, 456]
System.out.println(arr2.size());//2
//9.iterator():返回Iterator接口的实例,用于遍历集合元素。放在IteratorTest.java中测试(就是下面那个)
}
}
IteratorTest.java
使用iterator()遍历Collection
在test1中演示
Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
iterator是迭代器,是用来遍历的,它不装东西,coll是容器,iterator迭代的是容器coll中的数据。
Iterator遍历集合的两种错误写法
在test2中演示
Iterator迭代器remove()的使用
在test3中演示
IteratorTest.java代码
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
//迭代器Iterator用于迭代Collection,不用于迭代map
/**
* 集合元素的遍历操作,使用 迭代器Iterator接口
* 1.内部的方法:hasNext() 和 next()
* 2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,
* 默认游标都在集合的第一个元素之前。
* 3.内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove()
*
*/
public class IteratorTest {
@Test
public void test1(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
Iterator iterator = coll.iterator();
//方式一:
System.out.println(iterator.next());//第1个元素 123
System.out.println(iterator.next());//第2个元素 456
System.out.println(iterator.next());//第3个元素 Person{name='Jerry', age=20}
System.out.println(iterator.next());//第4个元素 Tom
System.out.println(iterator.next());//第5个元素 false
//报异常:NoSuchElementException
//System.out.println(iterator.next());//没有第六个元素,报异常
//方式二:不推荐(没啥理由,感觉这个不好)
// for(int i = 0;i < coll.size();i++){
// System.out.println(iterator.next());
// }
//方式三:推荐
hasNext():判断是否还有下一个元素
while(iterator.hasNext()){
//next()方法实现 ①指针下移 ②将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
}
@Test
public void test2(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
//错误方式一:
// Iterator iterator = coll.iterator();
// while((iterator.next()) != null){//这里判断下一个是不是空,下一个是123,非空,但是下一行,
// System.out.println(iterator.next());//这此时指针指在123上,判断下一个是否为空,下一个是456不为空,指针指向456,输出456
//判断了下一个 ,却输出了下下个
// }
//错误方式二:
//集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
while (coll.iterator().hasNext()){
System.out.println(coll.iterator().next());
//123
//123
//123一直输出123不停止
}
}
//测试Iterator中的remove()
//如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,
// 再调用remove都会报IllegalStateException。
@Test
public void test3(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
//删除集合中"Tom"
Iterator iterator = coll.iterator();
while (iterator.hasNext()){
//iterator.remove();在没调用next()之前调用remove()会报错
Object obj = iterator.next();
if("Tom".equals(obj)){
iterator.remove();
//iterator.remove();连着调用两次remove(),则在第二次报错
}
}
//遍历集合
iterator = coll.iterator();//重新指向开头的前面
while (iterator.hasNext()){
System.out.println(iterator.next());
//123
//456
//Person{name='Jerry', age=20}
//false 已移除Tom
}
}
}
//迭代器Iterator用于迭代Collection,不用于迭代map
新特性foreach 循环遍历集合或项目
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
/**
* jdk 5.0 新增了foreach循环,用于遍历集合、数组
*
*/
public class ForTest {
@Test
public void test1(){
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",20));
coll.add(new String("Tom"));
coll.add(false);
//for(集合元素的类型 局部变量 : 集合对象)
//内部仍然调用了迭代器。
for(Object obj : coll){//原理,取coll中的元素赋给obj,打印obj,取第二个元素给obj,打印obj,,,一直取到最后一个元素。
System.out.println(obj);
//123
//456
//Person{name='Jerry', age=20}
//Tom
//false
}
}
@Test
public void test2(){
int[] arr = new int[]{1,2,3,4,5,6};
//for(数组元素的类型 局部变量 : 数组对象)
for(int i : arr){
System.out.println(i);
}
//1
//2
//3
//4
//5
//6
}
//练习题
@Test
public void test3(){
String[] arr = new String[]{"MM","MM","MM"};
// //方式一:普通for赋值
// for(int i = 0;i < arr.length;i++){
// arr[i] = "GG";
// }
//方式二:增强for循环
for(String s : arr){//把arr中的取出来给s,然后给s赋值GG,s是新变量,arr不变
s = "GG";
}
for(int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
//MM
//MM
//MM
}
}
}