本篇博客分享的是java中常用的容器集合,大体分为了两类(Collection单列集合和Map双列集合),什么是双列,单列集合呢?看完这篇博客,或许你将有些许收获。Collection集合下主要讲解List集合和Set集合,而双列集合,我主要讲解HashMap集合。
Collection概述
是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素。
JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现。
创建Collection集合的对象:多态的方式
具体的实现类ArrayList: Collection c = new ArrayList ();
常用方法
Alt + 7 打开一个窗口,能够看到类的所有信息
add返回true
clear 清空集合中所有的元素
遍历:
Iterator:迭代器,集合的专用遍历方式
Iterator iterator () ; 返回次集合中元素的迭代器,通过集合的iterator () 方法得到
迭代器是通过集合的iterator ()方法得到的,所以说我们说它是依赖于集合而存在的
Iterator中的常用方法:
E next():返回迭代中的下一个元素
boolean hasNext():如果迭代具有更多元素,则返回true
NoSuchElementException:表示请求的元素不存在
下面展示一些 内联代码片
。
Iterator遍历代码实现
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class test { public static void main(String[] args) { Collection<Student> c=new ArrayList<Student>(); Student s1=new Student("秦潇",21); Student s2=new Student("王霖兴",22); c.add(s1); c.add(s2); Iterator<Student> it = c.iterator(); while (it.hasNext()){ Student s = it.next(); System.out.println(s.getName()+","+s.getAge()); } } }
List集合遍历的代码实现
//学生类 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; } } //-------------------------------------------------------- //测试类 public class ListDemo { public static void main(String[] args) { //创建List集合对象 List<Student> list = new ArrayList<Student>(); //创建学生对象 Student s1 = new Student("秦潇", 21); Student s2 = new Student("魏涛", 21; Student s3 = new Student("朱帅", 23); //把学生添加到集合 list.add(s1); list.add(s2); list.add(s3); //迭代器:集合特有的遍历方式 Iterator<Student> it = list.iterator(); while (it.hasNext()) { Student s = it.next(); System.out.println(s.getName()+","+s.getAge()); } System.out.println("--------"); //普通for:带有索引的遍历方式 for(int i=0; i<list.size(); i++) { Student s = list.get(i); System.out.println(s.getName()+","+s.getAge()); } System.out.println("--------"); //增强for:最方便的遍历方式 for(Student s : list) { System.out.println(s.getName()+","+s.getAge()); } } }
ArrayList集合是List集合的实现类,它的底层是数组结构实现,查询快、增删慢,它的一些常用方法可以参考List集合的常用方法。
LinkedList集合是List集合的实现类,它的底层是链表结构实现,查询慢、增删快,它有一些特有的常用方法
ConcurrentModificationException:当允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出异常
产生原因:
我们在通过迭代器遍历的过程中,通过集合去添加了元素,就造成了迭代器在获取元素的时候里面进行判断这个预期修改的值,和实际修改的值不一致的情况,这样就造成了并发修改异常
解决方案
用for循环遍历,用集合对象做相应的操作即可
目的:
简化数组和Collection集合的遍历
格式:
原理就是一个Iterator迭代器
概念:
数据结构是计算机存储、组织数据的方式。是值相互之间存在一种或多种特定关系的数据元素的集合
目的:
通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
栈:
先进后出
队:
先进先出
数组结构:
增删慢
查询快
链表结构:
增删快
查询慢
特点:
不包含重复元素的集合
没有带索引的方法,所以不能使用普通for循环遍历
创建
例如:
Set set = new HashSet();
概念:
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
获取哈希值:
Object类中有一个方法可以获取对象的哈希值
public int hashCode():返回对象的哈希码值
对象的哈希值特点:
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
哈希表:
在JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
在JDK8以后,在长度比较长的时候,底层实现了优化
特点
1、元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
2、没有带索引的方法,所以不能使用普通for循环遍历
3、由于是Set集合,所以不包括重复元素的集合
要理解好TreeSet必须先了解自然排序Comparable:
案例需求:
存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:
按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
实现步骤:
用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
案例代码实现
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; } 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 int compareTo(Student s) { // return 0; // return 1; // return -1; //按照年龄从小到大排序 int num = this.age - s.age; // int num = s.age - this.age; //年龄相同时,按照姓名的字母顺序排序 int num2 = num==0?this.name.compareTo(s.name):num; return num2; } } //------------------------------------------------ public class TreeSetDemo02 { public static void main(String[] args) { //创建集合对象 TreeSet<Student> ts = new TreeSet<Student>(); //创建学生对象 Student s1 = new Student("qinxiao", 21); Student s2 = new Student("wanglinxing", 21); Student s3 = new Student("weitao", 20); Student s4 = new Student("zhushuai", 23); Student s5 = new Student("liguang",22); Student s6 = new Student("longzeguo",23); //把学生添加到集合 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); ts.add(s6); //遍历集合 for (Student s : ts) { System.out.println(s.getName() + "," + s.getAge()); } } }
比较器排序Comparator的使用:
案例需求:
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求:
按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
实现步骤
用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
案例代码实现
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; } } //=================================================================== public class TreeSetDemo { public static void main(String[] args) { //创建集合对象 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { //this.age - s.age //s1,s2 int num = s1.getAge() - s2.getAge(); int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; return num2; } }); //创建学生对象 Student s1 = new Student("qinxiao", 21); Student s2 = new Student("wanglinxing", 21); Student s3 = new Student("weitao", 20); Student s4 = new Student("zhushuai", 23); Student s5 = new Student("liguang",22); Student s6 = new Student("longzeguo",23); //把学生添加到集合 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); ts.add(s6); //遍历集合 for (Student s : ts) { System.out.println(s.getName() + "," + s.getAge()); } } }
Map集合概述:
Interfacce Map <K,V> K:键的类型 V:值的类型
将键映射到值的对象,不能包括重复的键,每个键可以映射到最多一个值
举例:学生的学号和姓名
itheima001 林青霞
创建Map集合的对象:
多态的方式
具体的实现类HashMap
思路1:
获取所有键的集合,用keySet()方法实现
遍历键的集合,获取到每一个键,用增强for实现
根据键去找值,用get(Object key)方法实现
思路2
获取所有键值对对象的集合
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
根据键值对对象获取键和值
用getKey( )得到键
用getValue( )得到值
HashMap是Map的实现类,HashMap可实现快速存储和检索,但缺点是包含的元素是无序的,适用于在Map中插入、删除和定位元素。常用方法参考Map集合。
概述:
是针对集合操作的工具类
常用方法:
泛型概念:
是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型
它本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
参数化类型概念:
将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型
这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口
泛型定义格式:
<类型>:指定一种类型的格式。这里的类型可以看成是形参
<类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
泛型的好处
将运行时期的问题提前到了编译期间
避免了强制类型的转换
格式:
修饰符 class 类名 <类型>{ }
范例:
public class Generic { }
此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数用于表达泛型
格式:
修饰符 <类型> 返回值类型 方法名 (类型 变量名) { }
范例:
public void show(T t){ }
格式:
修饰符 interface 接口名 <类型> { }
范例:
public interface Generic { }
为了表示各种泛型List的父类,可以使用类型通配符
类型通配符 <?>
List <?> 表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能吧元素添加到其中
类型通配符上限:
<? extends 类型>
List<?extends Number >:它表示的类型是Number或者其子类类类型
我们不希望List <?>是任何泛型List 的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
类型通配符下限:
<? super 类型>
List <? super Number> :它表示的类型是Number或者其父类类型
概念:
可变参数又称为参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
注意事项:
可变参数又称为参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
这里的变量其实是一个数组, 如a
如果一个方法有多个参数,包含可变参数,可变参数要放在最后
使用:
Arrays
public static List asList(T… a):返回由指定数组支持的固定大小的列表
返回的集合不能做增删操作,可以做修改的操作
List
public static List of (E… elements): 返回包括任意数量元素的不可变列表
返回的集合不能做增删改操作
Set
public static Set of (E… elements): 返回一个包含任意数量元素的不可变集合
在给元素的时候,不能给重复的元素
返回的集合不能做增删操作,没有修改的方法