目录
一.Collection---------单列集合-------一次只能添加一个元素,如: 小明
1.Collection的常用方法
2.Collection的遍历
迭代器遍历
增强for遍历
Lambda表达式
3.List集合的特有方法
List集合的5种遍历方式
ArrayList集合
泛型
4.Set的方法和遍历方式
HashSet集合
LinkedHashSet集合
TreeSet集合
TreeSet集合默认的规则:
TreSet的两种比较方式(TreeSet创建的对象不能直接添加类,必须要进行比较,不然会报错)
一.Collection---------单列集合-------一次只能添加一个元素,如: 小明
Collection是单列集合的最高级接口,它的功能是全部单列集合都可以继承使用的
(上图来自黑马程序员)
List系列集合的特点: 添加的元素是有序(这里的有序指的是存进去时的顺序就是取出来时的顺序),可重复,有索引的
Set系列集合的特点: 添加的元素是无序,不重复,无索引
1.Collection的常用方法
方法名称 作用
public boolean add(E e) 把给定的对象添加到当前集合中
public void clear() 清空集合中所有的元素
public boolean remove(E e) 把给定的对象在当前集合中删除
public boolean contains(object obj) 判断当前集合中是否包含给定的对象public boolean isEmpty() 判断当前集合是否为空
public int size() 返回集合中元素的个数/集合的长度
代码示范:package Demo1; import java.util.ArrayList; import java.util.Collection; public class Demo1 { public static void main(String[] args) { Collection<String> coll = new ArrayList<>(); //1.coll.add coll.add("aaa"); coll.add("bbb"); coll.add("ccc"); System.out.println(coll); //2.coll.clear,清空 //coll.clear(); //System.out.println(coll); //3.coll.remove coll.remove("bbb"); System.out.println(coll); //4.coll.contains System.out.println(coll.contains("aaa")); //coll.isEmpty System.out.println(coll.isEmpty()); //coll.size int number = coll.size(); System.out.println(number); } }
结果展示:
2.Collection的遍历
迭代器遍历
特点: 迭代器遍历不依赖索引
迭代器在lava中的类是lterator迭代器是集合专用的遍历方式
(2)Collection集合获取迭代器
方法名称 作用
Iterator<E> iterator() 返回迭代器对象,默认指向当前集合的0索引
(3)lterator中的常用方法
方法名称 作用
boolean hasNext() 判断当前位置是否有元素,有元素返回true 没有元素返回false
E next() 获取当前位置的元素,并将迭代器对象移向下一个位置
代码示范:package Demo1; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo2 { public static void main(String[] args) { //创建集合 Collection<String> coll = new ArrayList<>(); //添加元素 coll.add("aaa"); coll.add("bbb"); coll.add("ccc"); coll.add("ddd"); //获取迭代器对象 Iterator<String> it = coll.iterator(); //迭代器就像一个箭头默认指向0索引位置 while(it.hasNext()){//is.hasNext(),判断该位置有没有元素,有返回true,没有返回false //it.next()的作用:获取元素并移动指针 String s1 = it.next(); System.out.println(s1); } //如果我们要继续进行第二次遍,只能在获取一个新的迭代器对象 } }
结果展示:
注意:
(1)报错NoSuchElementException(当前位置没有元素还强行获取元素就会报这个错误)
(2)迭代器遍历完了,指针不会复位
(3)循环中只能用一次next方法
(4)迭代器遍历时,不能用集合的方法进行增加或者删除
(要是删除的话可以用迭代器中的remove方法,增加的话目前还没有方法)
增强for遍历
(1)特点:
增强for的底层就是迭代器,为例简化迭代器的代码书写的(JDK5之后才有)
所以的单列集合和数组才能用增强for进行遍历
(2)格式:for(元素的数据类型 变量名: 数组或者集合){
}
代码示范:
package Demo1; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo2 { public static void main(String[] args) { //创建集合 Collection<String> coll = new ArrayList<>(); //添加元素 coll.add("aaa"); coll.add("bbb"); coll.add("ccc"); coll.add("ddd"); //增强for遍历 for (String s : coll) { System.out.print(s+" "); } System.out.println(); for (String s : coll) { s = "abc"; System.out.print(s+" "); } System.out.println(); System.out.println(coll); } }
结果展示:
注意: 修改for中的变量,不会修改集合中原本的数据
Lambda表达式
代码示范:
package Demo1; import java.util.ArrayList; import java.util.Collection; import java.util.function.Consumer; public class Demo3 { public static void main(String[] args) { Collection<String> coll = new ArrayList<>(); coll.add("aaa"); coll.add("bbb"); coll.add("ccc"); //匿名内部类形式 /*coll.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } });*/ //Lambda形式 coll.forEach(s -> System.out.println(s)); } }
结果展示:
3.List集合的特有方法
Collection的方法List都继承了
List集合因为有索引,所以多了很多索引操作的方法
方法名称 作用
void add(int index,E element) 在此集合中的指定位置插入指定的元素E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
代码示范:package Demo1; import java.util.ArrayList; import java.util.List; public class ListDemo { public static void main(String[] args) { //创建集合 //List是一个接口,无法直接创建对象, //所以只能创建它的实现类ArrayList的对象 List<String> list = new ArrayList<>(); //添加元素 list.add("aaa"); list.add("bbb"); list.add("ccc"); //void add(int index,E element) 在此集合中的指定位置插入指定的元素 //原来索引位置的元素会一次往后移 list.add(1,"ddd"); System.out.println(list); //E remove(int index) 删除指定索引处的元素,返回被删除的元素 String s1 = list.remove(0); System.out.println(s1); System.out.println(list); //E set(int index,E element) 修改指定索引处的元素,返回被修改的元素 String s2 = list.set(0,"eee"); System.out.println(s2); System.out.println(list); //E get(int index) 返回指定索引处的元素 String s3 = list.get(0); System.out.println(s3); System.out.println(list); } }
结果展示:
List集合的5种遍历方式
迭代器遍历 (在遍历的过程中需要删除元素时可以选择)
列表迭代器遍历 (在遍历的过程中需要添加元素时可以选择)
增强for遍历 (如果只想遍历可以选择)
Lambda表达式遍历 (如果只想遍历可以选择)
普通for循环 (因为List集合存在索引) (如果遍历时想操作索引可以选择)ArrayList集合
(1)利用空参创建的集合,在底层创建一个默认长度为0的数组
(2)添加第一个元素时,底层会创建一个新的长度为10的数组
(3)存满时会扩容1.5倍
(4)如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
泛型
格式: <数据类型>
注意: 泛型必须是引用数据类型
如果不使用泛型, 默认认为所有数据类型都是Object类型, 集合可以添加任意数据, 但是不能直接使用它的特有行为
好处: (1)统一数据类型
(2)把运行使其的问题提前到编译期间, 避免了强制类型转换可以出现的异常
泛型类
格式: public class 类名<E>{
}
代码示范:
package com.guaiwu; import java.util.Arrays; //泛型类 public class MyArrayList<E> { Object[] obj = new Object[10]; int size; public boolean add(E e){ obj[size] = e; size++; return true; } public E get(int index){ return (E)obj[index]; } @Override public String toString() { return Arrays.toString(obj); } }
package com.guaiwu; public class Test { public static void main(String[] args) { MyArrayList<String> list = new MyArrayList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); System.out.println(list); System.out.println(list.get(2)); System.out.println(list.toString()); } }
结果展示:
E可以理解为变量,但不是用来记录数据的,而是用来记录数据类型的(注意:E不是变量)
泛型方法
格式: 修饰符<E>返回类型 方法名(E 变量名){
}
代码示范:
package com.guaiwu; import java.util.ArrayList; //工具类 public class ListUtil { private ListUtil(){} public static <E>void addAll(ArrayList<E> list,E e1,E e2,E e3,E e4){ list.add(e1); list.add(e2); list.add(e3); list.add(e4); } public void show(ArrayList list){ System.out.println(list); } }
package com.guaiwu; import java.util.ArrayList; public class Test1 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); ListUtil.addAll(list,"aaa","bbb","ccc","ddd"); System.out.println(list); } }
结果展示:
泛型接口
格式: interface 接口名<E>{
}
泛型的通配符:
?也表示不确定的类型
但它可以进行类型的限定
? extends E: 表示可以传递E或者E所有的子类类型(这里的E指父类类名)
? extends E : 表示可以传递E或者E所有的父类类型(这里的E指子类类名)
4.Set的方法和遍历方式
Set系列集合的特点: 无序, 不重复, 无索引
没有自己的特定方法,和Collection的API基本一致
方法名称 作用
public boolean add(E e) 把给定的对象添加到当前集合中
public void clear() 清空集合中所有的元素
public boolean remove(E e) 把给定的对象在当前集合中删除
public boolean contains(object obj) 判断当前集合中是否包含给定的对象public boolean isEmpty() 判断当前集合是否为空
public int size() 返回集合中元素的个数/集合的长度代码示范:
package Demo; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.function.Consumer; public class Test { public static void main(String[] args) { //因为Set是接口,所以无法创建它的对象,只能创建它实现类的对象 Set<String> set = new HashSet<>(); set.add("aaa"); set.add("bbb"); set.add("ccc"); System.out.println(set); //迭代器遍历 Iterator<String> it = set.iterator(); while(it.hasNext()){ String s = it.next(); System.out.println(s); } //增强for遍历 for (String s : set) { System.out.println(s); } //Lambda表达式 set.forEach(s -> System.out.println(s)); } }
结果展示:
HashSet集合
没有添加特定的方法,和Collection的API基本一致
HashSet集合底层采取哈希表存储数据哈希表是一种对于增删改查数据性能都较好的结构
哈希表组成
JDK8之前:数组+链表
JDK8开始:数组+链表+红黑树哈希值:对象的整数表现形式
(1)根据hashCode方法算出来的int类型的整数
(2)该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算一般情况下,
(3)会重写hashCode方法,利用对象内部的属性值计算哈希值
对象的哈希值特点
(1)如果没有重写hashCode方法,不同对象计算出的哈希值是不同的(不同对象地址值不同)
(2)如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的(3)在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样(哈希碰撞)LinkedHashSet集合
没有添加特定的方法,和Collection的API基本一致
LinkedHashSet底层原理
不重复、无索引。有序、
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序TreeSet集合
特点:
(1)不重复、无索引、可排序(按照元素的默认规则 (有小到大)排序)
(2)TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好TreeSet集合默认的规则:
(1)对于数值类型: Integer, Double, 默认按照从小到大的顺序进行排序
(2)对于字符, 字符串类型: 按照字符在ASCII码表中能够的数字升序进行排序
TreSet的两种比较方式(TreeSet创建的对象不能直接添加类,必须要进行比较,不然会报错)
使用原则: 默认使用第一种, 如果第一种不能满足当前需求, 就使用第二种
方式一: 默认排序/自然排序:Javabean类实现Comparable接口指定比较规则
this: 表示当前要添加的元素
o: 表示已经在红黑树存在的元素
返回值:
负数: 认为要添加的元素是小的,存左边
正数: 认为要添加的元素是大的,存右边
0: 认为要添加的元素已经存在, 舍弃
代码示范:
package Demo; public class Student implements Comparable<Student>{ private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } @Override //根据年龄排序 public int compareTo(Student o) { return this.getAge()-o.getAge(); } }
package Demo; import java.util.TreeSet; public class Test { public static void main(String[] args) { Student s1 = new Student("zhangsan",23); Student s2 = new Student("lisi",24); Student s3 = new Student("wangwu",25); TreeSet<Student> ts = new TreeSet<>(); ts.add(s1); ts.add(s2); ts.add(s3); System.out.println(ts); } }
结果展示:
方式二:比较器排序: 创建TreeSet对象的时候, 传递比较器Comparator指定规则
练习:存入四个字符串,按照长度排序,如果长度一样则按照首字母排序
o1: 表示要添加的元素
o2: 表示已经存在红黑树中的元素
代码示范:
package Demo; import java.util.Comparator; import java.util.TreeSet; public class Test1 { public static void main(String[] args) { TreeSet<String> ts = new TreeSet<>((String o1, String o2)->{ //按照长度排序 int i = o1.length() - o2.length(); //如果长度一样按照字母排序 i = i == 0 ? o1.compareTo(o2) : i; return i; }); ts.add("abc"); ts.add("we"); ts.add("qor"); ts.add("aef"); ts.add("q"); System.out.println(ts); } }
结果展示: