集合
Collection接口
概述
数组和集合都是Java中提供的容器
集合: 英文译为 Collection,用来存放对象的容器,集合中可以存放不同类型的对象,并且集合的长度可变。
在编程时,常常需要集中存放多个数据,可以使用数组来保存多个对象,但数组长度不可变化,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组就有点无能为力了;
为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。
小结: 集合和数组的对比:
1)数组中的元素可以基本类型的值,也可以是对象; 而集合中只能保存对象
2)数组一旦指定了长度,长度就不能再改变; 而集合的长度是可以随时改变的
3)往数组中插入元素非常麻烦,需要将插入位置后面的元素往后移动; 或者删除数组中间位置的某一个元素, 需要将删除位置后的元素往前移动; 而如果往集合中插入元素或者删除集合中的某一个元素,直接使用现成的方法操作即可
集合的继承结构
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。
Collection接口
|-- List接口
|-- ArrayList类
|-- LinkedList类
|-- Set接口
|-- HashSet类
|-- TreeSet类
解释说明:
- Collection集合是所有单值集合的顶层接口, 其中定义了常用的用于操作集合以及集合中元素的方法
例如: 添加元素、删除元素、获取元素、获取集合长度、判断功能、将集合转成数组、迭代器遍历元素等功能
- List是Collection的子接口,特点是其中的元素是有序的(即:元素存入集合时的顺序和取出的顺序一致)
可以通过下标访问List中的元素,另,List集合中的元素是可以重复的(包括null)
- Set也是Collection的子接口,特点是其中的元素是无序(即:元素存入集合时的顺序和取出的顺序不一定一致)
无法通过下标访问Set中的元素,另外,Set集合中的元素是不可以重复的
学习集合的建议:
- 学习接口中提供的共性方法
- 通过实现类创建对象, 调用这些共性方法
常用方法
!!boolean add(E e)
– 往集合中添加指定元素e
boolean addAll(Collection c)
– 将小集合添加到大集合中
!!boolean isEmpty()
– 如果集合中没有任何元素(空集合), 返回true
boolean contains(Object o)
– 如果此集合中包含指定元素o, 则返回true
boolean containsAll(Collection c)
– 如果此集合中包含指定 集合c 中的所有元素,则返回 true。
– 例如c1中有 “a”,“b”,“c”,“d”, 而c2中有"a",“b”, 则c1包含c2, 返回true
若,c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”, 则c1不包含c2, 返回false
!!int size()
– 返回集合的大小(元素个数)
!!boolean remove(Object o)
– 从集合中删除指定的元素o, 删除成功则返回true
– 如果删除的元素不存在导致删除失败, 则返回false
– 如果元素o在集合中出现多次,仅删除第一个
boolean removeAll(Collection c)
– 删除此集合中那些也包含在指定集合c中的所有元素, 若有共同元素, 则删除并返回true
例如 c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”,
c1.removeAll(c2),只删除c1中两个共同的元素 “a”,“b”, 对c2没有影响
– 如果两个集合中没有共同元素, 则不删除, 返回false
boolean retainAll(Collection c)
– 仅保留此集合中那些也包含在指定集合c中的元素
例如 c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”,
c1.retainAll(c2),只保留c1中两个共同的元素 “a”,“b”, 对c2没有影响
void clear()
– 删除此集合中的所有元素
Object[] toArray()
– 将此集合转成对象数组
boolean equals(Object o)
– 比较此 collection 与指定对象是否相等。
!!Iterator iterator()
– 返回此集合中所有元素组成的迭代器。
实例1:CollectionDemo1
package collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author少珩
* @data 2022/3/21 20:09
* JAVA集合框架
* 集合和数组一样,都是保存一组元素的工具,但是集合将元素的操作都封装了方法,操作非常简便
* 并且集合提供了很多的不同的实现供我们使用
* java.util.Collection是所有集合的顶级接口,里面定义了所有的集合都必须要具备的功能和方法
* 集合中有两类常用的子类:
* java.util.List: 可重复的集合,且有序,通过称之为线性表
* java.util.Set: 不可重复的集合
*/
public class CollectionDemo1 {
public static void main(String[] args) {
//集合中只能存放引用类型
Collection c = new ArrayList();
/*
* 向集合添加元素
* 需要调用add方法" boolean add(E e) 这个E是泛型,这里先理解为是Object
* 向指定的集合添加元素,如果元素添加成功,返回true,否则返回false
* */
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
//[one, two, three, four, five]
System.out.println(c);
c.add(123);//会触发自动装箱 c.add(Integer.valueOf(123));
/*
* int size()
* 返回当前集合的元素个数
* 区别于数组的length
* */
int size = c.size();
System.out.println("集合的长度:"+size);
/*
* 判断集合是否为一个空集,当size=0是,也就是空集,返回true
* */
boolean empty = c.isEmpty();
System.out.println("集合是否为空集:"+empty);
//clear 方法可以被清空
c.clear();
System.out.println(c);
System.out.println("集合的长度:"+c.size());
System.out.println("集合是否为空集:"+c.isEmpty());
}
}
实例2:CollectionDemo2
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
/**
* @author少珩
* @data 2022/3/21 20:59
*/
public class CollectionDemo2 {
public static void main(String[] args) {
Collection c = new ArrayList();
//Collection c = new HashSet();//不能存储重复元素的
c.add(new Point(1, 2));
c.add(new Point(3, 4));
c.add(new Point(5, 6));
c.add(new Point(7, 8));
c.add(new Point(9, 0));
c.add(new Point(1, 2));//重复元素不能放在set集合
/*
* 集合中存储对象,存储的是对象的内存地址
* 如果不想让集合输出的是内存地址,想要输出的更直观
* 需要在Ponit中重写对应的toString,
* 集合的输出格式:
* [元素1.toString(),元素2.toString(),....]
* */
System.out.println(c);
Point p = new Point(1, 2);
/*
* 判断当前集合是否包含指定的元素
* boolean contains(Object o)
* 元素是否包含,取决于该元素是否与集合现有的元素存在equals比较结果为true的情况
* 默认比较的是内存地址,我们通常用来比较对象的属性,如果属性相同,就判断是统一元素,
* 返回true即可,但是需要对象中重写equals方法
* */
boolean contains = c.contains(p);
System.out.println("c集合是否包含元素p:"+contains);
/*
* remove方法删除元素时,也是删除与集合中equals比较为true的元素
* 对于List集合而言,由于可以存放重复元素,这种情况只会删除第一个
* */
c.remove(p);
System.out.println(c);
}
}
Point
package collection;
import java.util.Objects;
/**
* @author少珩
* @data 2022/3/21 21:00
* 使用当前类作为集合元素测试相关操作
*/
public class Point {
private int x;
private int y;
//生成全参构造,set,get alt+insert
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
实例3:CollectionDemo3
package collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author少珩
* @data 2022/3/21 21:23
*/
public class CollectionDemo3 {
public static void main(String[] args) {
Collection c = new ArrayList();
Point p = new Point(1, 2);
c.add(p);//将p存入到集合中
System.out.println("p:"+p);//p:Point{x=1, y=2}
System.out.println("c:"+c);//c:[Point{x=1, y=2}]
p.setX(2);//将p对象x属性修改为2
System.out.println("p:"+p);//p:Point{x=2, y=2}
System.out.println("c:"+c);//c:[Point{x=2, y=2}]
}
}
实例4:CollectionDemo4
package collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author少珩
* @data 2022/3/21 21:59
* 集合间的操作
*/
public class CollectionDemo4 {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("java");
c1.add("c++");
c1.add(".net");
System.out.println("c1:"+c1);
Collection c2 = new ArrayList();
c2.add("android");
c2.add("ios");
c2.add("java");
System.out.println("c2:"+c2);
/*
* 将c2集合中的元素添加到c1集合
* boolean addAll(Collection c)
* 将给定的集合的所有的元素添加到当前的集合中(取并集)
* 操作后,集合中发生了改变,返回true
* */
c1.addAll(c2);
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
Collection c3 = new ArrayList();
c3.add("c++");
c3.add("ios");
c3.add("php");
System.out.println("c3:"+c3);
/*
* 判断c1集合是否包含c3
* boolean containsAll(Collection c)
*判断当前集合中是否包含指定的集合中的所有元素
* */
boolean containsAll = c1.containsAll(c3);
System.out.println("包含所有:"+containsAll);
/*
* 取交集
* 取出指定两个集合中的共同的元素
* */
c1.retainAll(c3);
System.out.println("c1:"+c1);
/*
* 删除交集 将c1集合与c3集合的公有的元素删除()
* */
c3.removeAll(c1);//此处c3会被删除公有的内容,c1不会受影响
System.out.println("c1:"+c1);
System.out.println("c3:"+c3);
}
}
集合的遍历
IteratorDemo
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author少珩
* @data 2022/3/23 19:45
* 集合的遍历
* Collection层面上是不支持随机访问的(根据指定的位置获取对应的元素)
* 但是集合支持遍历操作,我们可以通过遍历最终结果拿到每一个元素
* 集合提供了一种遍历的方式:迭代器模式
* 对应方法
* Iterator iterator()
* 该方法会返回一个用于遍历当前集合的迭代器对象
* java.util.Iterator是迭代器接口,定义了迭代器遍历集合的基本操作,所有的集合够提供了用于遍历
* 自身的元素的迭代器的实现类,我们无需记忆他们的名字,用多态的思想统一看做是Iterator对象即可
* 迭代器遍历集合遵循的步骤:问->取->删.其中删除不是必须的操作
*/
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
System.out.println(c);//[one, two, three, four, five]
//获取当前集合的迭代器对象
Iterator it = c.iterator();
/*
* boolean hasNext()
* 判断集合中是否还有下一个元素可以遍历,迭代器的起始位置可以理解为是集合中第一个元素之前,
* 因此第一次调用jasNext()就是判断集合中是否有第一个元素
* E next()
* 获取集合中下一个元素,获取后迭代器的位置就会自动向后移动一个元素
* */
while (it.hasNext()){
String next = (String) it.next();
System.out.println(next);
//判断遍历的元素是否是'#'
if("#".equals(next)){
//如果是'#',就删除
/*
* 迭代器在遍历的过程中,不能通过集合的方法来增删元素,否则会抛异常:
* java.util.ConcurrentModificationException
* */
//c.remove(next);
/*
* 迭代器提供了remove方法,可以将本次通过next方法获取到的元素从集合中删除
* */
it.remove();
}
}
System.out.println(c);
}
}
增强型for循环
NewForDemo
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author少珩
* @data 2022/3/23 20:13
* JDK5推出时,推出了一个新特性:增强型for循环
* 通过也称为新循环
* 新循环并不能取代传统for循环的工作,只能为了使用相同的语法来遍历集合或者数组
* 语法:
* for(元素类型 e : 遍历的集合或者数组){
* 输出元素e
* }
*/
public class NewForDemo {
public static void main(String[] args) {
String[] array = {"one","two","three","four","five"};
//传统for循环遍历 array.fori
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
//新循环遍历数组 array.for
for( String e : array ){
System.out.println(e);
}
/*
* JDK5之后,还推出了一个特性:泛型
* 泛型也称为参数化类型,他的原型就是Object,
* 泛型的目的是让我们将定义的Object类型当做什么看待
* 如果不指定泛型,那么类型当成Object类型,如果指定了E的类型,
* 所有设置到的E的位置都变成对应类型
* public class User<E>{
* public E getName(E e)
* }
* User<String> a = new User();
* String d = a.getName("ccc");
* */
Collection<String> c = new ArrayList();
c.add("一");
c.add("二");
c.add("三");
c.add("四");
c.add("五");
for( String s : c){
System.out.println(s);
}
//改成成下面的样子
Iterator it = c.iterator();
while(it.hasNext()){
String str = (String) it.next();
System.out.println(str);
}
}
}