集合
1,集合的引入
集合和数组都是对多个数据进行存储操作的结构,都是Java容器。
说明:此时的存储,主要是指内存层面的存储,不涉及持久化的存储(如硬盘)
2,集合的两种体系简介
其中:
一,Collection接口中的:
①List子接口:存储有序的、可重复的数据。–>类似“动态”数组
②Set子接口:存储无序的、不可重复的数据。–>类似高中讲的集合(无序性、确定性、互异性)
二,Map接口:存储一对(key-value)数据。类似函数:y=f(x),
一个key不可对应多个value,但不同的key可以对应同一个value。
3, 集合体系一:Collection接口
3.1,Collection接口中的常用方法:
以下列举了Collectin接口中定义的14种方法的使用:
①首先自定义一个Person类:
package com.atguigu.java;
import java.util.Objects;
//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) {
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);
}
}
② 演示Collection中的14种方法
package com.atguigu.java;
import org.junit.Test;
import java.util.*;
/**
* Collection接口:
* ①List接口:存储有序的、可重复的数据。-->类似“动态”数组
* List接口的主要实现类:ArrayList、Linkedlist、Vector。
* ②Set接口:存储无序的、不可重复的数据。-->类似高中讲的集合(无序性、确定性、互异性)
* Set接口主要实现类:HashSet、LinkedHashSet、TreeHashSet
* Map接口:双列集合,存储一对。类似函数:y=f(x),一个key不可能对应多个value,但不同的key可以对应同一个value。
* 主要实现类:HashMap、LinkHashMap、TreeMap、Hashtable、Properties
*
* 由于JDK不提供此接口的任何直接实现,而是提供更具体的子接口,所以以下演示的抽象方法通过Collection的子接口(List接口)的实现类ArrayList来测试。
*/
public class CollectionTest {
@Test
public void test(){
// Collection接口中的方法的使用:而这些方法都是抽象的,所以只能拿它的实现类测试
Collection coll=new ArrayList(); //此处我们拿ArrayList实现类进行测试
//1,add(Object e):将元素e添加到集合coll中。形参为Object型。
coll.add("AA"); //传入Object类型的参数
coll.add("BB"); //传入Object类型的参数
coll.add(123); //注意:此处由于基本数据类型123经历了自动装箱,所以可以添加进去。
coll.add(new Date()); //传入Object类型的参数
//2,size():获取添加的元素的个数,没有添加时为0。
System.out.println(coll.size()); //4
//3,addAll():将coll1集合中的元素添加到当前的集合中
Collection coll1=new ArrayList();
coll.add(456);
coll.add("CC");
coll.addAll(coll1);
System.out.println(coll.size()); //6
System.out.println(coll); //可以查看具体元素。此处括号内相当于调用ArrayList实现类中重写的toString()。
//4,isEmpty():判断当前集合是否有元素(实际是看size是否为0)
System.out.println(coll.isEmpty()); //false
//5,clear()清空集合元素 :执行后,对象还在,只是数据被清空
coll.clear();
System.out.println(coll.isEmpty()); //true
System.out.println("**********");
Collection coll2=new ArrayList();
coll2.add(123);
coll2.add(456);
coll2.add(new String("Tom"));
coll2.add(false); //实际变为包装类Boolean---自动装箱
coll2.add(new Person("Jerry",20));
//通过以下几个方法理解理解知识点:要求向Collection接口实现类的对象中添加数据数据obj时,要求obj所在类要重写equals(),我们在自定义的Person类中重写了equals()方法
/*
6,contains(Object obj):判断当前集合中是否包含obj。判断时会调用obj对象所在类的equals()方法。
所以要求:向Collection接口实现类的对象中添加数据数据obj时,要求obj所在类要重写equals()
*/
boolean contains=coll2.contains(123);
System.out.println(contains); //true
System.out.println(coll2.contains(new String("Tom"))); //true。此处实际调用的是equals()方法,比较内容而非地址。String中已经重写equals()
System.out.println(coll2.contains(new Person("Jerry",20))); //true。此处实际调用的是Object类下的equals()方法,比较地址。如果自定义类Person中没有重写equals()方法,结果为false
//7,containsAll(Collection coll3):判断形参coll3中的所有元素是否都存在于当前集合中
Collection coll3= Arrays.asList(123,456); //实例化新方式:数组转化为集合,asList方法返回值类型为List,List又是Collection的一个子接口--(多态)
System.out.println(coll2.containsAll(coll3)); //true
System.out.println("*******");
//8,remove(Object obj):从当前集合中移除obj元素。返回值类型为布尔型,表示是否移除成功。
coll2.remove(123); //其中也会调用equals(),先判断有无123,所以也需要重写元素所在类的equals(),123对应包装类Integer已经重写过了,此处可以移除
System.out.println(coll2); //[456, Tom, false, Person{name='Jerry', age=20}]。
coll2.remove(new Person("Jerry",20)); //在自定义的Person类重写equals()后可以移除
System.out.println(coll2); //成功遍历
System.out.println("**************");
//9,removeAll(Collection coll):从当前集合中移除coll中所有元素(移除的是共有的),此方法也要调用equals()方法。
Collection coll4=Arrays.asList(1234,456);
coll2.removeAll(coll4); //移除共有元素 456
System.out.println(coll2); //[Tom, false]
}
@Test
public void test1(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
//10,retainAll(Collection coll1):返回布尔型,获取当前集合和coll1集合的交集元素,并返回给当前集合。
//Collection coll1=Arrays.asList(123,456);
//coll.retainAll(coll1);
//System.out.println(coll); //[123, 456]。求完交集后,修改当前集合coll
//11,equals() :判断当前集合与形参集合元素内容是否相同。
Collection coll2=new ArrayList();
coll2.add(123);
coll2.add(456);
coll2.add(new String("Tom"));
coll2.add(false);
coll2.add(new Person("Jerry",20));
System.out.println(coll.equals(coll2)); //true(内容一样)。注意如果交换元素顺序,则会变为false。因为ArrayList是List接口的实现类;List接口存储有序、可重复数据
}
@Test
public void test2(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
//12,hashCode():返回当前对象哈希值
System.out.println(coll.hashCode()); //700178533。类似随机数,指定存储地址
//13,toArray():集合转换为数组
Object[] arr = coll.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); //遍历数组元素
}
//拓展:数组也可以转化为集合。调用Arrays的静态方法---asList()
List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"}); //List属于Collection
System.out.println(list); //[AA, BB, CC]
}
}
特别注意:
向Collection接口实现类的对象中添加数据数据obj时,要求obj所在类要重写equals()。
3.2,Iterator接口方式遍历集合元素
第十四个方法——iterator():
返回 Iterator接口(迭代器接口) 的实例,用于遍历集合元素。
3.2.1,Iterator接口遍历集合元素
代码理解:
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 集合元素的遍历操作:使用迭代器Iterator接口
*/
public class IteratorTest {
@Test
public void test3(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
//14,iterator():返回Iterator接口(迭代器接口)的实例,用于遍历集合元素
Iterator iterator = coll.iterator();
//方式一演示:此方法遍历较麻烦。
//System.out.println(iterator.next()); //123
//System.out.println(iterator.next()); //456
//System.out.println(iterator.next()); //Tom
//System.out.println(iterator.next()); //false
//System.out.println(iterator.next()); //Person{name='Jerry', age=20}
//再执行System.out.println(iterator.next())会抛异常:NoSuchElementException
//方式二演示:使用for循环。
//for (int i = 0; i < coll.size(); i++) {
// System.out.println(iterator.next());
//}
//方式三(推荐)演示:推荐使用hasNext()和next()搭配,开发中最常用
while(iterator.hasNext()){ //判断还有没有元素,有则进入循环
//next():①指针下移 ②将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
}
}
迭代器的执行原理:
Iterator遍历集合两种错误的写法
(根据迭代器执行原理分析错误之处):
错误写法一:
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorTest {
@Test
public void test3(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
Iterator iterator = coll.iterator();
//错误写法1:
while((iterator.next())!=null){ //此处直接调next()会往下走
System.out.println(iterator.next()); //直接调next()会往下走
}
}
}
运行会报NoSuchElementException异常,并且会跳着输出。因为直接调next()会往下走一步。
-
next()作用:① 指针下移 ②将下移以后集合位置上的元素返回
错误写法二:
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorTest {
@Test
public void test3(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
Iterator iterator = coll.iterator();
//错误写法2:
while(coll.iterator().hasNext()){ //匿名方式
System.out.println(coll.iterator().next()); //会不断输出123
}
}
}
运行会不断输出123。原因是:集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
3.2.2,Iterator接口的remove()方法
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 测试Iterator接口中的remove():可以在遍历的时候删除集合元素
*/
public class IteratorTest {
@Test
public void test3(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
Iterator iterator = coll.iterator(); //得到迭代器对象
//删除集合中”Tom“数据
while (iterator.hasNext()){
Object obj = iterator.next();//获取值。多态
if ("Tom".equals(obj)){ //如果有”Tom“数据,进行移除
iterator.remove();
}
}
//重新遍历集合
iterator=coll.iterator(); //上一个while循环指针已经走到头了,所以此处需要重新生成迭代器对象
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
3.3,foreach循环方式遍历集合或数组元素
package com.atguigu.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
/**
* 集合的第二种遍历方式:foreach循环
* Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
*
*/
public class ForTest {
@Test
public void test1(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new String("Tom"));
coll.add(false);
coll.add(new Person("Jerry",20));
//for(集合中元素的类型 局部变量:集合对象)
for(Object obj:coll){ //Object为集合中元素的类型,obj相当于我们定义的局部变量
System.out.println(obj);
}
}
//foreach遍历数组
@Test
public void test2(){
int[] arr=new int[]{1,2,3,4,5,6};
//for(数组中元素的类型 局部变量:数组对象)
for(int i:arr){
System.out.println(i);
}
}
}