一、集合的高级功能
- 所有带All的功能:
Collection集合的高级功能:
boolean addAll(Collection c):添加一个集合中的所有元素
boolean removeAll(Collection c):删除集合的所有元素
删除一个元素算是删除还是删除所有算删除?
删除一个算删除(当前这个元素都包含)
boolean containsAll(Collection c) :判断是否包含所有元素
包含一个元素算包含还是包含所有算包含
包含所有元素才返回true
boolean retainAll(Collection c):对集合取交集?返回值boolean 什么意思
举例:
public class CollectioDemo {
public static void main(String[] args) {
//创建两个集合对象
Collection c1 = new ArrayList() ;
//添加元素
c1.add("abc1") ;
c1.add("abc2") ;
c1.add("abc3") ;
c1.add("abc4") ;
/* c1.add("abc5") ;
c1.add("abc6") ;
c1.add("abc7") ;*/
Collection c2 = new ArrayList() ;
//添加元素
c2.add("abc1") ;
c2.add("abc2") ;
c2.add("abc3") ;
c2.add("abc4") ;
c2.add("abc1") ;
c2.add("abc5") ;
c2.add("abc6") ;
c2.add("abc7") ;
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
//boolean addAll(Collection c):添加一个集合中的所有元素
// System.out.println(c1.addAll(c2));
//boolean removeAll(Collection c):删除集合的所有元素
// System.out.println(c1.removeAll(c2));
// boolean containsAll(Collection c) :判断是否包含所有元素
// System.out.println(c1.containsAll(c2));
// boolean retainAll(Collection c):对集合取交集?返回值boolean 什么意思
System.out.println(c1.retainAll(c2));
/*
* A集合对B集合取交集,交集的元素保存在A集合中,返回值的结果判断A集合的元素是否有变化
* 有变化,就返回true
* 没有变化,就返回false!
*
* */
System.out.println("--------------------------");
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
}
}
- Collection获取功能:
集合的专有迭代器:Iterator iterator() :Collection接口的迭代器
迭代器属于集合的专有遍历方式
Iterator:接口
Object next()返回迭代的下一个元素。
boolean hasNext():判断迭代器中是否存在下一个元素
迭代器
interface Iterator{
boolean hasNext() ;
E next() ; //E :Element :代表任意类型 (Object)
}
<E>Element,<T> Type 存储元素类型
<K,V>:Key 键,Value值
interface Iterable{
Iterator iterator():将指定类型的元素在迭代器上进行遍历
}
interface Collection extends Iterable{
Iterator iterator():将指定类型的元素在迭代器上进行遍历
}
interface List extends Collection{
Iterator iterator():将指定类型的元素在迭代器上进行遍历
}
//具体子实现类
class ArrayList implements List{
public Iterator<E> iterator() {
return new Itr(); //创建Itr类对象
}
//ArrayList$Itr :成员内部类
private class Itr implements Iterator<E>{
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")//强制压制警告
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
}
}
Collection
迭代器的原理:就是实现了Iterator接口的子实现类
ArrayList:Itr内部类
List----> ListIterator:列表迭代器 接口----> ListItr内部类
举例1:
public class CollectionDemo {
public static void main(String[] args) {
//创建一个Collection对象
Collection c = new ArrayList() ;
//添加元素
c.add("hello") ;
c.add("world") ;
c.add("javaee") ;
//获取Collection集合的迭代器
//Iterator iterator()
Iterator it = c.iterator();
//获取集合中的下个元素
// Object next()返回迭代的下一个元素。
/* Object obj = it.next();
System.out.println(obj);
System.out.println(it.next());
System.out.println(it.next());*/
// System.out.println(it.next());//java.util.NoSuchElementException
//当前集合的元素取完了,迭代器它并没有去判断是否有下一个元素;如果能在获取之前,添加一个判断功能,防止出现的异常
/* if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}*/
//循环改进:while循环
while(it.hasNext()){
Object next = it.next(); //存储的元素 new String("hello") "hello"
// System.out.println(next);
//遍历同时获取子串长度
// System.out.println(next+"---"+next.length());
//向下转型
String s = (String) next;
System.out.println(s+"---"+s.length());
}
}
}
举例2:
/*需求:
* 现在使用Collection存储5个学生,姓名和年龄,使用Collection的迭代器遍历
*/
public class Student {
private String name ;
private int age ;
public Student() {
}
public Student(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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class CollectionDemo2 {
public static void main(String[] args) {
//创建Collection集合对象
Collection c = new ArrayList() ;
//创建5个学生
Student s1 = new Student("貂蝉",20) ;
Student s2 = new Student("王昭君",25) ;
Student s3 = new Student("杨玉环",22) ;
Student s4 = new Student("西施",27) ;
Student s5 = new Student("高圆圆",41) ;
//添加到集合中
c.add(s1) ;
c.add(s2) ;
c.add(s3) ;
c.add(s4) ;
c.add(s5) ;
//使用迭代器遍历
Iterator iterator = c.iterator();
while(iterator.hasNext()){
Object o = iterator.next();
//java.lang.ClassCastException :类转换异常
// String s = (String) o;//com.qf.collection_02.Student cannot be cast to java.lang.String
//由于必须考虑: 看集合存储的类型是什么类型!
Student s = (Student)o ;
System.out.println(s.getName()+"---"+s.getAge());
}
/* for (Object e : c) {
System.out.println(e);
}*/
}
}
举例3:
/* 需求:
* 有一个集合,给集合中添加一些字符串元素,如果这个集合中包含 "world"元素,
* 给集合新添加一个"javaee"元素,遍历集合!
*
*
* java.util.ConcurrentModificationException:并发修改异常
*
* 出现这个异常: 使用Iterator迭代器去遍历元素,不能使用集合操作元素
*
* 解决方案:
* 1)要么就是集合遍历,集合添加
* 2)要么迭代器去遍历元素,迭代器去添加元素
*/
public class CollectionDemo3 {
public static void main(String[] args) {
//创建一个集合对象
//Collection c = new ArrayList() ;
List list = new ArrayList() ;
//假设添加一些字符串元素
/*c.add("hello") ;
c.add("world") ;
c.add("android") ;*/
list.add("hello") ;
list.add("world") ;
list.add("android") ;
//遍历:使用Iterator iterator
//Iterator it = c.iterator();
// ListIterator lit = list.listIterator() ;
/* while(it.hasNext()){
Object obj = it.next();
String s = (String) obj;
if("world".equals(s)){
//添加元素
c.add("javaee") ;
}
}*/
/* while(lit.hasNext()){
Object obj = lit.next();
String s = (String) obj;
if("world".equals(s)){
//添加元素
//迭代器添加
lit.add("javaee") ;
}
}
//遍历集合
// Iterator it2 = c.iterator();
ListIterator lit2 = list.listIterator();
while(lit2.hasNext()){
Object obj = lit2.next() ;
System.out.println(obj);
}
*/
//集合遍历,集合添加
for(int x = 0 ; x < list.size() ; x ++){
String s = (String) list.get(x);
if(s.equals("world")){
list.add("javaee") ;
}
}
Iterator iterator = list.iterator();
while(iterator.hasNext()){
String s = (String) (iterator.next());
System.out.println(s);
}
}
}
二、List子接口
-
添加:
add(Object e)
remove()
contains()
…
Object[] toArray()
Iterator iterator() -
List集合特点:
有序的(存储和取出一致)
集合的元素是可以重复的 -
特有功能
void add(int index,Object element):在指定的位置处 添加元素
Object get(int index):通过角标可以获取指定的元素 + size() :普通for循环遍历
ListIterator listIterator(): 可以使用List集合的专有遍历方式
Object remove(int index):通过该角标删除指定的元素 -
List集合遍历方式有几种?
Object[] toArray()
Collection的迭代器:Iterator iterator()
size()+get()相结合
举例:
public class ListDemo {
public static void main(String[] args) {
//创建List集合对象
List<String> list = new ArrayList<String>() ;
//添加元素
list.add("hello") ;
list.add("world") ;
list.add("world") ;
list.add("javaee") ;
list.add("javaee") ;
System.out.println(list);
//void add(int index,Object element):在指定的位置处 添加元素
list.add(2,"android") ;
System.out.println(list);
//Object get(int index):通过角标可以获取指定的元素
String s = list.get(4);
System.out.println(s);
System.out.println("--------------------------");
// Object remove(int index):通过该角标删除指定的元素
System.out.println(list.remove(2)); //返回被删除的元素
System.out.println(list);
for(int x = 0 ; x < list.size() ; x ++){
String str = list.get(x);
System.out.println(str);
}
}
}
- 那么如果List集合中存储的是Student(自定义对象),遍历同时,去重!
学生有姓名,年龄
新建集合思想:
使用新集合对象判断元素不包含,就不重复!
contains方法底层依赖于equals方法
之前:List—底层重写了equals方法,必须他们的是否相同
现在存储自定义对象,成员信息一致,认为它同是一个人!
要去重复自定义对象,必须在当前类中重写equals以及 hashCode()
举例:
public class Student {
private String name ;
private int age ;
public Student() {
}
public Student(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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
public class ListTest {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>() ;
//创建一些学生
Student s1 = new Student("高圆圆",41) ;
Student s2 = new Student("高圆圆",41) ;
Student s3 = new Student("高圆圆",35) ;
Student s4 = new Student("文章",30) ;
Student s5 = new Student("马宝国",25) ;
Student s6 = new Student("王宝强",35) ;
Student s7 = new Student("文章",30) ;
list.add(s1) ;
list.add(s2) ;
list.add(s3) ;
list.add(s4) ;
list.add(s5) ;
list.add(s6) ;
list.add(s7) ;
//新建一个集合
List<Student> newList = new ArrayList<Student>() ;
//遍历以前的集合
Iterator<Student> it = list.iterator();
while(it.hasNext()){
Student student = it.next();
if(!newList.contains(student)) {
newList.add(student) ;
}
}
//遍历新集合
Iterator<Student> it2 = newList.iterator();
while(it2.hasNext()){
Student s = it2.next() ;
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
- List集合去重第二种方式:不让你新建集合怎么去重?
利用选择排序思想
使用0角标对应的元素和后面的元素进行比较,如果后面的元素重复了,将后面定义干掉,角标–
而且使用集合元素!
举例:
public class ListTests2 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>() ;
list.add("hello") ;
list.add("hello") ;
list.add("hello") ;
list.add("hello") ;
list.add("world") ;
list.add("world") ;
list.add("world") ;
list.add("world") ;
list.add("javaee") ;
list.add("javaee") ;
list.add("javaee") ;
list.add("php") ;
list.add("php") ;
list.add("php") ;
//利用选择排序
for(int x = 0 ; x < list.size()-1 ; x ++){//比较次数
for(int y = x + 1 ; y< list.size() ; y ++){
if(list.get(y).equals(list.get(x))){
//先删除后面的元素
list.remove(y) ;
y-- ;
}
}
}
//迭代器
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String s = iterator.next() ;
System.out.println(s);
}
}
}
举例:
/* 产生1-30 (6个)随机数:Random 将这元素集合中
*/
public class Test {
public static void main(String[] args) {
//创建随机数生成器
Random random = new Random() ;
//创建一个集合
ArrayList<Integer> list = new ArrayList<Integer>() ;
ArrayList<Integer> newList = new ArrayList<Integer>() ;
for(int x = 0 ;x < 6 ; x ++){
int num = random.nextInt(30) +1 ;
list.add(num) ;
}
//元素如何去重
//遍历list
//增强for
/*
for(存储类型 变量名: 集合对象){
}
*/
for(Integer i: list){
if(!newList.contains(i)){
newList.add(i) ;
}
}
//新集合遍历
for(Integer i : newList){
System.out.println(i);
}
}
}
- List的三个子实现的特点:
{11,22,33,44,55}
1). ArrayList
List 接口的大小可变数组的实现:底层数据结构是数组
数组—>查询元素 数组名称[角标]
查询快,增删慢
线程角度:
是一个不安全的类,不同步的,所以默认没有明确要求使用哪种集合都是使用ArrayList(执行效率高)
2). Vector
可以实现可增长的对象数组; 底层数据结构数组
数组—>查询元素 数组名称[角标]
查询快,增删慢
线程角度:
Vector 是同步的,-----线程安全可靠, 执行效率低
3). LinkedList
链接列表实现:底层数据结构是链表
查询慢:都需要从链接列表查到末尾
增删快:数据域和指针域; 使用中间互换!
线程角度:
实现不同步的,是一个线程不安全的类,执行效率高!
三、泛型
- 泛型:<集合中存储类型>
为了让我们集合的元素类型一致,所以Java提供了泛型,
模拟数组方式,在创建集合对象的时候,就已经明确了类型,防止出现安全问题!
<E>
格式:
集合<存储类型> 对象名 =new 子实现类名<存储类型>() ;
- 泛型的好处:
1)提供程序的安全性,避免了强制类型转换
2)将运行时期异常提前了编译时期
3)解决创建集合的黄色警告线问题 - 泛型应用范围:---->集合中使用居多! Class:反射中
泛型可以在接口上,也可以定义在类上,也可以在方法上使用!
举例:
//@SuppressWarnings("all"):jdk内置注解: 压制警告 注解(接口)
public class GenericDemo {
public static void main(String[] args) {
//回想我们的数组
//定义一个字符串数组
// String[] strArray = {"hello","world","javaEE",100} ;
Collection<String> c = new ArrayList<String>() ;
c.add("hello") ;
// c.add(100) ;
c.add("world") ;
c.add("javaee") ;
System.out.println(c);
System.out.println("---------------------------");
//迭代器
Iterator<String> it = c.iterator();
while(it.hasNext()){
String s = it.next() ;
System.out.println(s+"---"+s.length());
}
}
}
- 早期没有使用泛型之前,程序不安全
多态: 向下转型----->出现类型不匹配,存储的类型和接收的类中不一致(ClassCastException)
举例:
public class ObjectTool {
private Object obj ;
//定义设置数据的方法
public void set(Object obj){
this.obj = obj ;
}
//定义一个获取数据的方法
public Object get(){
return obj ;
}
}
public class ObjectToolTest {
public static void main(String[] args){
//创建工具类对象
ObjectTool objectTool = new ObjectTool() ;
objectTool.set("高圆圆"); //Object obj = new String ("") ;
//获取它的内容
String s = (String) objectTool.get();
System.out.println("姓名是:"+s);
//java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
//Integer i = (Integer) objectTool.get();
//System.out.println(i);
System.out.println("----------------------");
ObjectTool ot2 = new ObjectTool() ;
ot2.set(41); //Object obj = new Integer(41) ;
//String s2 = (String) ot2.get();//ava.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
//System.out.println(s2);
Integer i2 = (Integer) ot2.get();
System.out.println("年龄是:"+i2);
}
}
- 早期没有使用泛型之前,程序不安全
多态: 向下转型----->出现类型不匹配,存储的类型和接收的类中不一致(ClassCastException)
现在将泛型定义在类上:
可以提高程序安全性,避免了强制类型转换,将运行时期异常提前了编译时期
举例:
//改进:将泛型定义在类上
public class ObjectTool<T> {
private T obj ;
//定义设置数据的方法
public void set(T obj){
this.obj = obj ;
}
//定义一个获取数据的方法
public T get(){
return obj ;
}
}
public class ObjectToolTest {
public static void main(String[] args){
//创建ObjectTool<>对象:明确了类型
ObjectTool<String> ot = new ObjectTool<String>() ;
//ot.set(41) ;
ot.set("高圆圆");
//Integer i = ot.get() ;
String i = ot.get() ;
System.out.println("姓名是:"+i);
System.out.println("-------------------");
ObjectTool<Integer> ot2 = new ObjectTool<Integer>() ;
ot2.set(41);
//ot2.set("张佳宁");
Integer ii = ot2.get();
System.out.println("年龄是:"+ii);
}
}
举例:
* 将泛型定义在方法
*/
//public class ObjectTool<T> {
public class ObjectTool {
/* //定义一些成员方法
public void show(String s){
System.out.println(s);
}
public void show(boolean b){
System.out.println(b);
}
public void show(double d){
System.out.println(d);
}
public void show(char ch){
System.out.println(ch);
}*/
//优化:将泛型定义类方法上
public <T> void show(T t){ //提供这个方法的扩展性,形式参数可以是任意的类型:Object
System.out.println(t);
}
}
public class ObjectToolTest {
public static void main(String[] args) {
//创建ObjectTool
// ObjectTool ot = new ObjectTool() ;
/* ot.show("hello");
ot.show('h');
ot.show(true);
ot.show(12.56);*/
/*ObjectTool<String> ot = new ObjectTool<String>() ;
ot.show("hello");
ObjectTool<Integer> ot2 = new ObjectTool<Integer>() ;
ot2.show(100);*/
/*
* 之前将泛型定义在类上,方法的形式参数需要和类上的泛型类型保持一致,存在弊端
* 传递一些数据类型,需要通过类上的泛型来确定(创建对象),麻烦
* 能不能将泛型定义的方法上呢?
* */
ObjectTool ot = new ObjectTool() ;
ot.show(100);
ot.show(true);
ot.show("hello");
ot.show('A');
}
}
6. 泛型高级通配符(了解)
<?> :这个集合可以存储任意的Java数据类型 或者是Object
<? extends E>:向下限定: 当前是E这个类型或者是E类型的子类 (从后往前看符号)
<? super E>:向上限定:跟E这个类类型一致或者是它的父类
举例:
public class CollectionDemo {
public static void main(String[] args) {
//创建集合对象
Collection<?> c1 = new ArrayList<Object>() ;
Collection<?> c2 = new ArrayList<Animal>() ;
Collection<?> c3 = new ArrayList<Cat>() ;
Collection<?> c4 = new ArrayList<Dog>() ;
System.out.println("--------------------------------") ;
Collection<? extends Animal> c5 = new ArrayList<Animal>() ;
//Collection<? extends Animal> c6 = new ArrayList<Object>() ;
Collection<? extends Animal> c6 = new ArrayList<Cat>() ;
Collection<? extends Animal> c7 = new ArrayList<Dog>() ;
System.out.println("--------------------------------") ;
Collection<? super Cat> c8 = new ArrayList<Cat>() ;
Collection<? super Cat> c9 = new ArrayList<Animal>() ;
Collection<? super Cat> c10 = new ArrayList<Object>() ;
}
}
class Animal{
}
class Dog extends Animal{}
class Cat extends Animal{}