概述:提供一种存储空间可变的存储模型,存储数据容量可以随时发生改变
单列: 双列
张三 itcast 张三
李四 itcast2 李四
王五 itcast3 王五
单列可重复: 单列不可重复:
张三 张三
李四 李四
张三
ArrayList
ArrayList
可调整大小数组
eg:ArrayList
ArrayList构造方法和添加方法
public ArrayList()
创建一个空的集合对象
public boolean add(E e)
将指定元素追加到此集合的末尾
public void add(int index,E element)
在集合中的指定位置插入指定元素
ArrayList array = new ArrayList<>();
array.add("hello");
array.add("world");//此时array为[hello,world]
array.add(1,"javase");//此时array为[hello,javase,world]
array.add(4,"javase");//此时报错,显示结合越界
ArrayList集合常用方法
array.xxxxxx
来调用,以下index都会出现越界报错
public boolean remove(Object 0)
删除指定元素,返回删除是否成功
public E remove(int index)
删除指定索引处元素,返回被删除元素
public E set(int index,E element)
修改指定索引处元素,返回被修改元素
public E get(int index)
返回指定索引处元素
public int size()
返回集合中的元素个数
Collection
Collection集合概述和使用
Collection集合概述
- 单例集合顶层接口,表示一组对象,这些对象也被成为collection的元素
- JDK不提供该接口的直接实现,而是提供更具体的子接口(如Set和List)实现
创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
Collection
c = new ArrayList ();
Collection集合常用方法
-
boolean add (E e)
:添加元素,返回boolean类型结果显示添加是否成功
c.add("hello");c.add("world");//输出c为[hello,world]
-
boolean remove(Object o)
:从集合中移除指定的元素,返回boolean类型显示是否成功
c.remove(hello);
-
void clear()
:清空集合中的元素
c.clear;
-
boolean contains(Object o)
:判断集合中是否存在指定的元素,返回boolean类型结果
c.contains("world");
-
boolean isEmpty()
:判断集合是否为空
c.isEmpty();
-
int size()
:返回集合的长度,也就是集合中元素的个数
c.size();
Collection集合的遍历
iterator:迭代器,集合的专用遍历方式
- Iterator
iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到 - 迭代器通过集合iterator()方法得到,所以我们说它是依赖于集合而存在的
Iterator中的常用方法
-
E next()
:返回迭代中的下一个元素 -
boolean hasNext()
:如果迭代具有更多元素,则返回true
Collection c = new ArrayList();//创建集合对象
String s = "hello";//创建元素
c.add(s);//添加元素到集合
c.add("world");//添加元素到集合
Iterator(String) it = c.iterator();//通过集合对象获取迭代器对象
while(it.hasNext()){
String s = it.next();
System.out.println(s);//先输出hello,再输出world
}
List
List集合概述和特点
List集合概述
- 有序集合,用户可以精准控制列表每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中元素
- 与set集合不同,列表通常允许重复的元素
List集合特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("hello");// 元素可重复
Iterator it = list.iterator();//List继承自Collection,可以用迭代器方式遍历
while(it.hasNext()){
String s=it.next();
System.out.println(s);
}
List集合特有方法
Collection没有,但是ArrayList,LinkedList有
-
void add(int index,E element)
:在此集合中的指定位置插入指定的元素 -
E remove(int index)
:删除指定索引处的元素,返回被删除元素 -
E set(int index,E element)
:修改指定索引处元素,返回被修改的元素 -
E get(int index)
:返回指定索引处的元素
并发修改异常
Iterator it = list.iterator();
while(it.hasNext()){
String s=it.next();
//用迭代器获取元素时modCount(实际修改值)和expectedModCount(预期修改值)会比较是否相同
if(s.equals("world")){
list.add("javaee");//单独添加元素会使集合中元素长度改变,造成两值不一致,进而抛出异常
}
System.out.println(s);
}
//会抛出ConcurrentModificationException的异常
修改为
for(int i=0;i
ListIterator(该集合特有遍历方式)
ListIterator:列表迭代器
- 通过List集合的listIterator()得到,所以说它是List集合特有的迭代器
- 运行程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,别获取列表中迭代器当前位置
ListIterator中常用方法
E next()
:返回迭代中的下一个元素
boolean hasNext()
:如果迭代具有更多元素,则返回true
E previous()
:返回列表中的上一个元素
boolean hasPrevious()
:如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e)
:将指定的元素插入列表
List list=new ArrayList();
......
ListIterator lit=list.listIterator();
while(lit.hasNext()){//正向遍历
String s=lit.next();
System.out.println(s);
}
while(lit.hasPrevious()){//反向遍历
String s=lit.pervious();
System.out.println(s);
}
while(lit.hasNext()){//直接通过lit添加,而不像之前通过list才能添加
String s=lit.next();
if(s.equals("world")){
lit.add("javaee");
}
}
增强for循环(最方便遍历方式)s
目的:简化数组和Collection集合的遍历
- 实现Iterable接口的类允许其对象成为增强型for语句的目标
- 内部原理是一个Iterator迭代器
格式
for(元素数据类型 变量名: 数组或者Collection集合){
//在此处使用遍历即可,该变量就是元素
}
eg:
int[ ] arr={1,2,3,4,5};
for(int i : arr){
System.out.println(i);
}
String[ ] strArray={"hello","world","java"};
for(String s : strArray){
System.out.println(i);
}
List集合子类特点
List集合常用子类:ArrayList,LinkedList
- ArrayList:底层数据结构是数组,查询快,增删慢
ArrayList
array = new ArrayList () - LinkedList:底层数据结构是链表,查询慢,增删快
LinkedList
array = new LinkedList ()
LinkedList集合的特有功能
-
public void addFirst(E e)
在该列表开头插入指定的元素 -
public void addLast(E e)
将指定的元素追加到此列表的末尾 -
public E getFirst()
返回此列表的第一个元素 -
public E getLast()
返回此列表中的最后一个元素 -
public E removeFirst()
从此列表删除并返回第一个元素 -
public E removeLast()
从此列表删除并返回最后一个元素
Set
Set集合概述和特点
set集合特点
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通for循环遍历
set存储字符串并遍历
Set set=new HashSet();
//HashSet对集合的迭代顺序不做任何保证
set.add("hello");
set.add("world");
set.add("java");
for(String s : set){
System.out.println(s);//输出字符串的顺序不一定和输入的一样,但一定不重复
}
哈希值
定义:JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中返回哈希值方法
-
public int hashCode()
:返回对象的哈希码值 - 同一个对象多次调用
hashCode()
方法返回的哈希值相同 - 默认情况下,不同对象哈希值不同,但是重写类中
hashCode()
方法,可以让不同对象哈希值相同
eg:System.out.println("hello".hashCode())
s1,s2两对象相同,不想重复录入,就要在类中重写equals和hashCode方法
HashSet集合概述和特点
HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证(存储和取出元素顺序不一定一致)
- 没有带索引的方法,不能使用普通for循环遍历
- 由于是Set接口实现类,不包含重复元素集合
HashSet存储字符串并遍历
HashSet hs=new HashSet();
hs.add("hello");
hs.add("world");
hs.add("java");
for(String s : hs){
System.out.println(s);
}
HashSet集合保证元素唯一性流程
要保证元素唯一性,需要重写hashCode()和equals()方法
哈希表
JDK8前,底层采用数组+链表实现,是一个元素为链表的数组
JDK8之后,在长度比较长的时候,底层实现了优化
LinkedHashSet集合概述和特点
LinkedHashSet集合特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,元素的存储和取出一致
- 由哈希表保证元素唯一性,没有重复元素
LinkedHashSet存储字符串并遍历
LinkedHashSet lhs=new LinkedHashSet();
hs.add("hello");
hs.add("world");
hs.add("java");
for(String s : lhs){
System.out.println(s);
}
TreeSet集合概述和特点
TreeSet集合特点
- 元素有序,但并非存储和取出顺序,而是根据构造方法按照一定规则排序
TreeSet()
:根据其元素的自然排序进行排序(从小到大顺序)
TreeSet(Comparator comparator)
:根据指定的比较器进行排序 - 没有带索引的方法,不能用普通for循环遍历
- 由于是Set接口实现类,不包含重复元素集合
TreeSet存储整数并遍历
TrssSet ts=new TreeSet();//基本类型存储时用的是对应包装类类型,所以int用Integer
ts.add(30);
ts.add(40);
ts.add(20);
for(Integer i : ts){
System.out.println(i);
}
自然排序Comparable使用
存储对象并遍历,使用TreeSet无参构造方法,年龄由小到大排序,否则按照姓名字母排序
Student类
public class Student implements Comparable{//类中必须添加Comparable接口
private String name;
private int age;
......
public int compareTo(Student s){
//return 0;s1和s2比较时,返回值一直一致,s2无法添加
//return -1;s1和s2比较时,s2一致比s1小,先输出
//return 1;s1和s2比较时,s2一致比s1大,后输出
int num=this.age-s.age;//获取s2的值减去s1的值的差
int num2=num==0?this.name.compareTo(s.name):num;//获取s2和s1相比首字母大小
return num2;
}
}
Main主函数
TreeSet ts=new TreeSet<>();
Student s1=new Student("Tom",24);
Student s2=new Student("Jack",18);
ts.add(s1);
ts.add(s2);
for(Student s:ts){
System.out.println(s.getName()+","+s.getAge());
}
自然排序就是让元素所属的类实现Comparable接口,重写compareTo(E e)方法
重写方法时分清主要和次要比较条件
比较器排序Comparator使用
存储对象并遍历,使用TreeSet带参构造方法,年龄由小到大排序,否则按照姓名字母排序
public static void main(String[] args) {
//主函数中用匿名内部类直接重写compare方法
TreeSet ts=new TreeSet(new Comparator() {
@Override
public int compare(User u1, User u2) {
int num=u1.getAge()-u2.getAge();
int num2=num==0?u1.getName().compareTo(u2.getName()):num;
return num2;
}
});
......
}
比较器排序时,就是让集合构造方法接收Comparator的实现类对象,重写compare(E e1,E e2)方法;重写方法时分清主要和次要比较条件;
泛型
概述
泛型提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型
本质是参数化类型:将类型由原来具体类型参数化,然后在调用时传入具体类型
应用:泛型类、泛型方法、泛型接口
定义格式
-
<类型>
:指定一种类型格式,这里类型可以看成形参eg:Collection
-
<类型1,类型2>
:指定多种类型格式,这些类型都可以看作形参 - 具体调用时候给定类型可以看成实参,且只能是引用数据类型
优势
- 把运行时期的问题提前到了编译期间
-避免了强制类型转换
泛型类
定义格式
修饰符 class 类型<类型>{ }
eg:
public class Generic{//E为任意标识,是个形式参数表示泛型
private E e;
public E getE(){return e;}
public void setE(E e){this.e = e;}
}
使用泛型类
Generic g1 = new Generic(); g1.setE("Jack");
Generic g2 = new Generic(); g2.setE(30);
Generic g3 = new Generic(); g3.setE(true);
泛型方法
定义格式
修饰符 <类型> 返回值类型 方法名(类型 变量名){ }
eg:
public class Generic{
public void show(T t){ //泛型方法写在任意类都可
System.out.println(t);
}
}
使用泛型方法
Generic g = new Generic();
g.show("Jack");
g.show(30);
g.show(true);
泛型接口
定义格式
修饰符 interface 接口名<类型>{ }
eg:
//泛型接口
public interface Generic{
void show;
}
//泛型接口对应实现类
public class GenericImpl implements Generic{
public void show(T t){
System.out.println(t);
}
}
主函数中使用泛型接口
Generic g1=new GenericImpl();
g1.show("Jack");
Generic g2=new GenericImpl();
g2.show(30);
类型通配符
类型通配符:>
- 表示各种泛型List的父类
-
List>
表示元素类型未知List,它的元素可以匹配任何的类型 -
List>
仅表示它是各种泛型List的父类,并不能把元素添加其中
List> list1 = new ArrayList
类型通配符上限: extends 类型>
-
List extends Number>
只代表某一类泛型List的父类 -
List extends Number>
表示类型是Numbers或者其子类
List extends Number> list5 = new ArrayList();
List extends Number> list6 = new ArrayList();
类型通配符下限: super 类型>
-
List super Number>
表示类型是Numbers或者其父类
List super Number> list7 = new ArrayList
可变参数
即参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的
格式:修饰符 返回值类型 方法名(数据类型...变量名){ }
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,40));
public static int sum(int...a){//此时a实际上就是一个数组名,所以可以用增强for求和
int sum=0;
for(int i : a){
sum+=i;
}
return sum;
}
public static int sum(int b,int...a){......}
//此形式下第1个数存入b,其余的存入数组a
方法中形参实际是一个数组
如果一个方法由多个参数,包含可变参数,可变参数要放在最后
可变参数使用
Arrays工具类中有一个静态方法
-
public static
:返回由指定数组支持的固定大小的列表List asList
List
list=Arrays.asList("hello","world","java");//可以修改元素,但不可增删
List接口中有一个静态方法
-
public static
:返回包含任意数量元素的不可变列表List of(E...elements)
List
list=List.of("hello","world","java","world");//不可增删修改
Set接口中有一个静态方法
-
public static
:返回一个包含任意数量元素的不可变集合Set of(E...elements)
Set
set=set.of("hello","world","java");//不可增删,不可有重复元素,无修改方法
Map集合
Map集合概述和特点
Map集合概述
- Interface Map
K是键的类型,V是值的类型 - 将键映射到值的对象;不能包含重复的键;每个键可以映射最多一个值
eg:B17041223 张三 (学号不重复做键,姓名做值)
创建Map集合对象
- 多态方式
- 具体实现类HashMap
Map map = new HashMap();
map.put("B17041223","张三");
map.put("B17041231","李四");
map.put("B17041223","王五");//此时会根据键,把原来的张三替换成王五
Map集合的基本功能
-
V put(K key,V value)
添加元素 -
V remove(Object key)
根据键删除键值对应元素 -
V clear()
移除所有的键值对应元素 -
boolean containsKey(Object key)
判断集合是否包含指定的键 -
boolean containsValue(Object value)
判断集合是否包含指定的值 -
boolean isEmpty()
判断集合是否为空 -
int size()
集合的长度,可就是集合中键值对的个数
Map集合的获取功能
-
V get(Object key)
根据键获取值 -
Set
获取所有键的集合keySet()
Set
keySet=map.keySet() -
Collection
获取所有值的集合values()
Collection
values=map.values() -
Set
获取所有键值对对象的集合> entrySet()
Map集合的遍历
方式1
1.获取所有键的集合,用keySet()方法实现
2.遍历键的集合,获取到每一个键,用增强for实现
3.根据键去找值,用get(Object key)方法实现
Map map = new HashMap();
map.put("张无忌","赵敏");
map.put("黄蓉","郭靖");
map.put("杨过","小龙女");
Set keySet = map.keySet();
for(String key:keySet){
String value = map.get(key);
System.out.println(key+","+value);
}
方式2
1.获取所有键值对对象的集合
Set
方法
2.遍历键值对对象的集合,得到每一个键值对对象
增强for实现,得到每一个Map.Entry
3.根据键值对对象获取键和值
用getKey()
得到键
用getValue()
得到值
Map map = new HashMap();
map.put("张无忌","赵敏");
map.put("黄蓉","郭靖");
map.put("杨过","小龙女");
Set> entrySet = map.entrySet();
for(Map.Entry me:entrySet){
String key=me.getKey();
String value=me.getValue();
System.out.println(key+","+value);
}
案例
键盘录入1个字符串,统计字符串中每个字母出现次数,输出形式为“a(5)b(7)c(2)”
//键盘录入字符串
Scanner sc =new Scanner(System.in);
System.out.println("请输入1个字符串:");
String line = sc.nextLine();
//创建HashMap集合,键是Character,值是Integer
HashMap hm=new HashMap<>();
//遍历字符串得到每1个字符
for(int i=0;i keySet = hm.keySet();
for(Character key:keySet){
Integer value=hm.get(key);
sb.append(key).append("(").append(value).append(")");
}
String result=sb.toString();
//输出结果
System.out.println(result);
集合嵌套案例
创建ArrayList集合,存储3个元素,每个元素都是HashMap,每个HashMap键和值都是String,并遍历
//创建ArrayList集合
ArrayList> array=new ArrayList>();
//创建HashMap集合,并添加键值对元素
HashMap hm1=new HashMap<>();
hm1.put("孙策","大乔");
hm1.put("周瑜","小乔");
//把HashMap作为元素添加到ArrayList集合
array.add(hm1);
//创建HashMap集合,并添加键值对元素
HashMap hm2=new HashMap<>();
hm2.put("郭靖","黄蓉");
hm2.put("杨过","小龙女");
//把HashMap作为元素添加到ArrayList集合
array.add(hm2);
//创建HashMap集合,并添加键值对元素
HashMap hm3=new HashMap<>();
hm3.put("令狐冲","任盈盈");
hm3.put("张无忌","赵敏");
//把HashMap作为元素添加到ArrayList集合
array.add(hm3);
//遍历ArrayList集合
for(HashMap hm:array){
Set keySet = hm.keySet();
for(String key:keySet){
String value = hm.get(key);
System.out.println(key+","+value);
}
}
创建1个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每个ArrayList的元素是String,并遍历
//创建HashMap集合
HashMap> hm=new HashMap<>();
//创建ArrayList集合,并添加元素
ArrayList sgyy=new ArrayList<>();
sgyy.add("诸葛亮");
sgyy.add("刘备");
//把ArrayList作为元素添加到HashMap集合
hm.put("三国演艺",sgyy);
//创建ArrayList集合,并添加元素
ArrayList xyj =new ArrayList<>();
xyj.add("唐僧");
xyj.add("孙悟空");
//把ArrayList作为元素添加到HashMap集合
hm.put("西游记",xyj);
//创建ArrayList集合,并添加元素
ArrayList shz=new ArrayList<>();
shz.add("武松");
shz.add("鲁智深");
//把ArrayList作为元素添加到HashMap集合
hm.put("水浒传",shz);
Set keySet = hm.keySet();
for(String key:keySet){
System.out.println(key);
ArrayList value = hm.get(key);
for(String s:value){
System.out.println("\t"+s);
}
}
Collections
Collections概述和使用
Collections类的概述
- 针对集合操作的工具类
Collections类的常用方法
-
public static
将指定的列表按升序排序> void sort(List list) -
public static void reverse(List> list)
反转指定列表中的元素的顺序 -
public static void shuffle(List> list)
使用默认的随机源随机排列指定的列表
List list = new ArrayList();
list.add(20);list.add(10);list.add(40);list.add(30);
Collections.sort(list);
Collections.reverse(list);
Collections.shuffle(list);