集合是指具有某种特定性质的具体的或抽象的对象汇总而成的集体,有时集合也称之为容器,java中在util包下存放了所有的基本集合。
2.关系图: 3.集合与数组的对比:数组存储的特点:
初始化后,长度确定
定义好后,元素类型确定只能操作指定类型的数据
4.集合的框架结构数组存储的弊端:
1.一旦初始化以后,其长度就不可修改。
2.数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
3.获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
4.数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
二、Collection接口 1.相关概念:|----Collection接口:单列集合,用来存储一个一个的对象
|----List接口:存储有序的、可重复的数据。 -->“动态”数组
|----ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
|----LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
|----Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储
|----Set接口:存储无序的、不可重复的数据 -->数学概念上的“集合”
|----HashSet:作为Set接口主要实现类;线程不安全;可以存null值
|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
|----TreeSet:可以按照添加对象的指定属性,进行排序。
|----Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x)
|----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
|----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。对于频繁的遍历操作,此类执行效率高于HashMap。
|----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序,底层使用红黑树
|----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
|----Properties:常用来处理配置文件。key和value都是String类型
2.Collection接口常用方法:Collection接口是List、Set和Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也可用于操作List和 Queue集合。
JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
在JDK 5.0之前,Java集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object类型处理;从JDK 5.0增加了泛型以后,Java集合可以记住容器中对象的数据类型。
boolean add(E e);添加一个数据到集合中
boolean addAll(Collection extends E> c); 将一个集合数据添加到另外一个集合中
// Collection extends E>:元素 是E本类或者继承的E,才能添加到另外一个集合中
boolean remove(Object obj);删除指定的元素
//Object类型的原因是,可以传任何类型的元素 但,只有与列表中数据类型一致的元素,且有的元素被删除才会返回true
boolean removeAll(Collection extends E> c); 删除的是交集
boolean contains(Object obj); 集合中是否包含这个元素 如果包含返回true
boolean containsAll(Collection extends E> c);一个集合是否另外一个集合子集合
boolean isEmpty(); 判断集合是否为空
Object[] toArray(); 将集合转为Object类型数组
int size(); 返回集合中元素的个数
void clear() 清空元素
boolean retainAll(Collection> c)
//arraylist.retainAll(Collection c);
sites.retainAll(sites2);
System.out.println("保留的元素: " + sites);
ArrayList 1: [Google, Runoob, Taobao]
ArrayList 2: [Wiki, Runoob, Google]
保留的元素: [Google, Runoob]
//集合1 .retainAll(集合2)
//保留交集,若两个集合不存在交集,则 集合1经过此方法后为空
3.遍历集合中的数据
(一般情况)
1.使用for循环 // 针对采用索引存储的集合,有序
2.增强for循环 // for each
3.使用迭代器 // Iterator 迭代器接口
以代码为例,展示三种遍历集合方式的用法:
前提代码: Collection4.有关于Iterator迭代器接口:list1 = new ArrayList<>(); list1.add(1); list1.add(2); list1.add(5); list1.add(3); System.out.println(list1); //for循环遍历数组 //将集合转为Object类数组 Object[] obj = list1.toArray(); System.out.println("-----------------"); for (int i = 0; i < obj.length; i++) { System.out.println(obj[i]); } //增强for循环 Collection list2 = new ArrayList<>(); list2.add(0); list2.add(1); list2.add(2); list2.add(3); list2.add(4); for (Integer n : list2) { System.out.println(n); } //使用迭代器(详情见下面迭代器的讲解) Iterator iterator = list2.iterator(); //默认的 游标在第一个元素之前 //集合:{[游标]e1,e2,e3,e4,e5} System.out.println(iterator.hasNext()); //true 游标后有元素吗?有 所以true //{[游标]e1,e2,e3,e4,e5} System.out.println(iterator.next()); //0 返回e1,游标游向下一个元素e2 //{e1,[游标]e2,e3,e4,e5} System.out.println(iterator.next()); //1 返回e2,游标游向下一个元素e3 //{e1,e2,[游标]e3,e4,e5} System.out.println(iterator.next()); //2 返回e3,游标游向下一个元素e4 //{e1,e2,e3,[游标]e4,e5} System.out.println(iterator.next()); //3 返回e4,游标游向下一个元素e5 //{e1,e2,e3,e4,[游标]e5} System.out.println(iterator.next()); //4 返回e5,游标游到末尾 //{e1,e2,e3,e4,e5[游标]} //System.out.println(iterator.next()); //Excetion NoSuchElementException //游标再向下游已经没有元素了,所以Excetion System.out.println(iterator.hasNext()); //false 游标后还有元素吗? 无 所以false System.out.println("-----------------"); Iterator iterator = list2.iterator(0); // (index i) ==> 0 //上面的例子中游标已经从前游到后,我们将游标位置归零,放到第一个元素前 //正序遍历,使用while循环,利用iterator.hasNext()方法返回值是布尔类型值的特性 while (iterator.hasNext()){ //判断此游标后是否有元素 System.out.println(iterator.next()); //返回当前游标所指向的元素,并游向该元素的后一个元素 } //逆序遍历方法将会在ListIterator接口中有所体现 //逆序遍历 前提是此时 光标指在最后一个元素 while (iterator.hasPrevious()){ //判断此游标前是否有元素 System.out.println(sli.previous()); //返回当前游标所指向的元素,并游向该元素的前一个元素 } //如果想要直接逆序还可以 Iterator iterator = list2.iterator(index i); //i为游标所在集合中的位置的映射, 集合: {e1,e2,e3,e4,e5} index: {[0]e1,[1]e1,[2]e1,[3]e1,[4]e1,[5]null} //如上例,若要打印输出 4 3 2 1 0 则 i为5,游标在下标为[5]的位置
概述:
Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
迭代器模式:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所
有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
Iterator接口的方法:
【逆序遍历方法将会在ListIterator接口中有所体现】
中文:
| default void | forEachRemaining(Consumer super E> action) 对每个剩余元素执行给定的操作,直到所有元素都被处理或动作引发异常。 |
| boolean | hasNext() 如果迭代具有更多元素,则返回 true 。 |
| E | next() 返回迭代中的下一个元素。 |
| default void | remove() 从底层集合中删除此迭代器返回的最后一个元素(可选操作)。 |
英文:
5.在类中存自定义对象import java.util.ArrayList;
import java.util.Collection;
class Person {
private String name;
private int age;
//set get
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;
}
//构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//无参构造
public Person() {
}
//toString
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
public class Demo03_Person {
public static void main(String[] args) {
Person person = new Person("万三",25);
System.out.println(person); //地址
//在一个类中重写toString方法
//将内存地址转换为容易阅读的字符串
System.out.println(person); //已经转换 默认形式 --> 自定形式
System.out.println("--------------");
Collection list = new ArrayList<>();
list.add(person);//若没有tostring()方法,集合中放的是Object类tostring方法默认的形式
list.add(new Person("公孙放",26));
System.out.println(list);
//转换为Object数组后再强转取出来对象
Object[] objects = list.toArray(); //***
Person person1 = (Person) objects[0];//***
System.out.println(person1.getName());
//在List接口中我们可以直接调用get(index i)方法
//E get(int index)
}
}
//输出结果
com.liu.javastudy_day16.Demo03_Person
Person{name='万三', age=25}
Person{name='万三', age=25}
--------------
[Person{name='万三', age=25}, Person{name='公孙放', age=26}]
万三
Process finished with exit code 0
总结收获:集合是一种常用的存取数据的容器,要熟记方法,掌握用法



