Day12–泛型+集合
一、泛型
1.概述
- 用来约束集合中元素的类型,标志是<>,英文是Generics
2.泛型使用的位置
-
类上/接口上—定义格式:修饰符 class 类名<泛型>{}
class Demo<E>{}
-
方法上 —定义格式:修饰符 <泛型> 返回值类型 方法名(参数(使用泛型)){}
public <E> void show(E e){}
3.基本用法
package cn.tedu.api;
import java.util.ArrayList;
import java.util.List;
//测试 泛型的使用--通常配合集合一起使用
public class Test02_Generic {
public static void main(String[] args) {
//泛型: 用来约束集合中的元素类型,如果不符合反应的类型检查,那么在编译期就会报错
List<String> list = new ArrayList();
//list.add(1); //不符合泛型的类型检查
//list.add(1.1); //不符合泛型的类型检查
list.add("Jack"); //符合泛型的类型检查
System.out.println(list);
//可以用泛型约束元素的类型,但是<>内不能是基本类型,必须是引用类型
List<Integer> list2 = new ArrayList();
list2.add(1); //符合泛型的类型检查
list2.add(5); //符合泛型的类型检查
list2.add(156); //符合泛型的类型检查
//list2.add(1.1); //不符合泛型的类型检查
//list2.add("Jack"); //不符合泛型的类型检查
System.out.println(list2);
}
}
4.高级用法
package cn.tedu.api;
import java.util.Arrays;
//测试 泛型的通用性
public class Test03_Generic {
public static void main(String[] args) {
String[] s = {"杨幂","迪丽热巴","古力娜扎","Anglelababa","马尔扎哈","刘沛霞"};
print(s);
Integer[] i = {1,2,3,4,5};//自动装箱 -- 把基本类型包装成包装类型
print(i);
Double[] d = {1.1,2.2,3.3,4.4,5.5};
print(d);
}
//
// public static void print(String[] a){
// for(String s : a){
// System.out.println(s);
// }
// }
// public static void print(Integer[] b){
// for(Integer i : b){
// System.out.println(i);
// }
// }
// public static void print(Double[] c){
// for(Double d : c){
// System.out.println(d);
// }
// }
// 泛型出现在方法上,必须两个位置同时出现--方法返回前和参数列表里
public static <E> void print(E[] a){
for(E s : a){
System.out.println(s);
}
}
}
5.泛型的高级用法之foreach循环和泛型的约束作用
- 作用1:类型检查 + 报错前置
- 作用2:泛型的通用性
package cn.tedu.lianxi;
import java.util.ArrayList;
import java.util.List;
//测试 泛型的作用
public class Test3 {
public static void main(String[] args) {
// method();//类型检查
method2();//增强通用性
}
//打印数组里的数据
private static void method2() {
Integer[] a = {1, 2, 3, 4, 5};
print(a);
Double[] b = {1.1, 2.2, 3.3, 4.4, 5.5};
print(b);
String[] c = {"杨幂", "Anglelababa", "古力娜扎", "迪丽热巴"};
print(c);
}
//作用2:泛型的通用性
//在方法上用泛型,两个位置必须同时出现..
/*private static <E> void print(E[] a) {
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}*/
//TODO foreach循环/高效for循环。。。。
//1,使用的场景---数组|collection集合
//2,语法:for(遍历得到的数据类型 变量名 :要遍历的容器){}
private static <E> void print(E[] a) {
for (E s : a)
System.out.println(s);
}
//作用1:类型检查 + 报错前置
private static void method() {
//模拟数组:类型检查+报错前置
// int[] a = {1.1,2,3,4,5};
//1,集合里可以添加 任意类型 的元素
List list = new ArrayList();
list.add(10);
list.add(2.3);
list.add(true);
list.add("hello");
//2,使用泛型 约束list2集合里元素的类型String
List<String> list2 = new ArrayList();
list2.add("100");
list2.add("200");
// list2.add(100);//没有通过泛型的类型检查
//3,泛型的<??>--??不能是基本类型,必须是引用类型
List<Integer> list3 = new ArrayList();
//1是基本类型,约束的必须是包装类型,为什么不报错?
list3.add(1);
//自动装箱-把基本类型变成包装类型 new Integer(1)
}
}
二、集合
1.概述
- 都是可以存大量的数据
- 数组:长度一旦定义不能改变 + 数据的类型必须统一 + 优势是查询快
- 集合:长度可变 + 元素的类型不限 + 有查的快的,有增删快的
2.继承结构
- Collection:顶级接口–不能new,学方法
- List:子接口–不能new,学方法
- ArrayList:实现类–学习new
- LinkedList:实现类–学习new
- Set:子接口–不能new,学方法
- HashSet:实现类–学习new
- List:子接口–不能new,学方法
3.集合的继承结构
4.Collection接口
1.概述
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set和 List)实现。
2.共性方法
略,查字典
3.测试
package cn.tedu.api;
import java.awt.*;
import java.util.*;
import java.util.List;
//测试 Collection接口的共性方法
public class Test04_Collection {
public static void main(String[] args) {
//1.创建多态对象
Collection<Integer> collection = new ArrayList();
List<Integer> list = new ArrayList();
list.add(2);
list.add(3);
list.add(4);
//2.调用方法
collection.add(1);//向集合中添加1
System.out.println(collection);
collection.addAll(list);//向集合中添加list集合
System.out.println(collection);
//collection.clear();//移除集合中全部元素
System.out.println(collection.contains(1));//判断是否包含1
System.out.println(collection.containsAll(list));//判断是否包含list集合中的元素
System.out.println(collection.equals(123));//判断和123是否相等
System.out.println(collection.hashCode());//返回此集合的哈希码值
System.out.println(collection.isEmpty());//判断集合是否为空
// collection.remove(1);//从集合中移除1
// System.out.println(collection);
//
// collection.removeAll(list);//从集合中移除list集合中的元素
// System.out.println(collection);
// collection.retainAll(list);//仅保留此集合与list集合中相同的元素,其他元素全部移除
// System.out.println(collection);
System.out.println(collection.size());//返回此元素中的元素数量
Object[] os = collection.toArray();//把此集合里的元素存入Object[]里
System.out.println(Arrays.toString(os));
Iterator iterator = collection.iterator();//使用Iterator迭代器,迭代获取集合里的元素
while (iterator.hasNext()){//hasNext(),判断--有元素就返回true, 迭代
Object obj = iterator.next();//获取元素
System.out.println(obj);
}
}
}
三、List接口
1.特点
- 有序
- 有索引
- 可以重复
- 存多个null
2.常用方法
--继承自Collection接口的
--lüe
--自己扩展特有的(根据索引的操作)
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection<? extends E> c)
E get(int index)
返回列表中指定位置的元素。
int indexOf(Object o)
int lastIndexOf(Object o)
ListIterator<E> listIterator()
返回此列表元素的列表迭代器(按适当顺序)。
E remove(int index)
移除列表中指定位置的元素(可选操作)。
E set(int index, E element)
用指定元素替换列表中指定位置的元素(可选操作)。
List<E> subList(int fromIndex, int toIndex)
3.List的两个实现类
4.测试
package cn.tedu.api;
import java.util.*;
//测试 list
public class Test01_List {
public static void main(String[] args) {
//1.创建对象
List<Integer> list = new ArrayList();
//2.调用方法
//继承自Collection接口的方法
list.add(1);
System.out.println(list);
list.add(2);
System.out.println(list);
list.add(3);
System.out.println(list);
list.add(null);
System.out.println(list);
List<Integer> list2 = new ArrayList();
list2.add(5);
list2.add(5);
list2.add(6);
list2.add(7);
list.addAll(list2);
System.out.println(list);
// list.clear();
// System.out.println(list);
System.out.println(list.contains(1));
System.out.println(list.containsAll(list));
System.out.println(list.equals(123));
System.out.println(list.hashCode());
System.out.println(list.isEmpty());
Iterator<Integer> i = list.iterator();
while (i.hasNext()){
Integer obj = i.next();
System.out.println(obj);
}
System.out.println("----------------------------------");
//list.remove((Integer)2);//也能实现,不过不好,其他类型不一定能用
//list.remove(2);//拿着基本类型的2当做索引
list.remove(new Integer(5));//拿着包装类型的5当做集合中的元素 如果集合中含有多个,只能删除一个
System.out.println(list);
System.out.println("----------------------------------");
//list.removeAll(list2);
//System.out.println(list);
//list.retainAll(list2);
//System.out.println(list);
System.out.println(list.size());
//自己扩展特有的(根据索引的操作)
list.add(4,100);
System.out.println(list);//在索引处4的位置添加新元素100
System.out.println(list.get(4));//获得索引为4处的元素
System.out.println(list.indexOf(null));//获取null元素第一次出现时的索引
System.out.println(list.lastIndexOf(1));//获取1元素最后一次出现时的索引
list.remove(4);//移除索引为4的元素
System.out.println(list);
list.set(0,null);//将索引为0的元素替换成null
System.out.println(list);
System.out.println(list.subList(2,5));//将索引处为2至索引5之间的元素截取成原集合的子集合[2,5)
//集合的迭代方法
//方式1:Iterator<E> iterator() -- 继承自Collection接口方法
Iterator<Integer> it=list.iterator();
while(it.hasNext()){//hasNext() 用来判断
Integer in=it.next();//next()用来获取数据并把指针后移
System.out.println(in+"::::1");
}
//方式2:ListIterator<E> listIterator()
ListIterator<Integer> it2 = list.listIterator();
while (it2.hasNext()){//hasNext()用来判断后面有没有元素
Integer in=it2.next();//next()获取后面的一个元素
System.out.println(in);
}
//逆向遍历 -- 前提是:必须先顺序遍历 -- 不用!!
while (it2.hasPrevious()){//判断前面有元素吗
Integer in=it2.previous();//获取前面的一个元素
System.out.println(in);
}
//面试题:iterator() 和 listIterator()的区别?
//iterator()来自父接口Collection/listIterator()是List子接口特有的
//返回值不同,Iterator是父接口/ListIterator是子接口,子接口能用所有父接口的功能,而且拓展了逆向遍历的方法 们~~~
//方式3:普通for,根据下标迭代
for (int i2 =0; i2<list.size();i2++){
System.out.println(list.get(i2));
}
//方式4:foreach--for(得到的数据的类型 变量名 : 数组/Collection集合){}
for(Integer i2 :list){
System.out.println(i2);
}
}
}
四、ArrayList
1.特点
- 是List接口的实现类,底层维护的是一个 可变长的 数组Object[]。方便查询.
2.创建对象
ArrayList()
3.常用方法
同List接口
4.测试
package cn.tedu.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
//测试 ArrayList
public class Test02_ArrayList {
public static void main(String[] args) {
//1.创建对象
//ArrayList本质上是维护了一个Object[],为了可以存放各种类型的元素
//jdk1.6里,一旦创建对象,就自动分配10个容量来存储元素
//jdk1.8里,如果不向集合中存放数据,默认是空数组
//直到调用add()时,才开始自动扩容,默认容量是10
//如果数组容量不够了,会自动扩容,扩容的方式:int newCapacity = oldCapacity + (oldCapacity >> 1); -- 以前容量的1.5倍
ArrayList<Integer> list = new ArrayList();
ArrayList<Integer> list1= new ArrayList();
//2.调用方法
list.add(1);//添加元素
list.add(2);
list.add(2);
list.add(null);
list.add(3);
System.out.println(list);
list.add(5,4);//在指定索引处添加元素
System.out.println(list);
list1.add(11);
list1.add(22);
list1.add(33);
list1.add(44);
list.addAll(list1);//添加集合
System.out.println(list);
list.addAll(0,list1);
System.out.println(list);
//list.clear();//清除元素
//System.out.println(list);
list.clone();
System.out.println(list);
System.out.println(list.contains(11));//判断集合中是否包含11这个元素
System.out.println(list.get(5));//返回索引为5的元素
System.out.println(list.indexOf(22));//返回元素22第一次出现时的索引
System.out.println(list.lastIndexOf(22));//返回元素22最后一次出现时的索引
System.out.println(list.isEmpty());//判断集合是否为空
list.remove((Integer) 44);//移除元素44
System.out.println(list);
list.remove(1);//移除索引为1的元素
System.out.println(list);
list.set(0,11111);//将索引值为0的元素替换成11111
System.out.println(list);
System.out.println(list.size());//返回集合的长度
Object[] ob = list.toArray();//将集合的元素存放在Object[]中
System.out.println(Arrays.toString(ob));
//扩展:模拟ArrayList存储数据
//ArrayList本质上是维护了一个Object[],为了可以存放各种类型的元素
//集合有多长,容量就给多大,不浪费内存
Object[] obj = new Object[list.size()];
//遍历数组
for(int i = 0 ; i< obj.length;i++){
//从集合里获取元素,存入数组中
obj[i]=list.get(i);
}
//打印数组里的数据
System.out.println(Arrays.toString(obj));
//3.迭代集合
Iterator<Integer> it = list.iterator();
while (it.hasNext()){
Integer in = it.next();
System.out.println(in);
}
}
}
五、LinkedList
1.特点
- 是List接口的实现类,拥有List接口的所有特点
- 底层维护了一个链表结构,对于链表上的节点,有两个特殊位置是开头及结尾的元素的位置.
2.创建对象
LinkedList()
构造一个空列表。
3.常用方法
--继承自父接口List /Collection的方法们
--略
--自己扩展的方法们
void addFirst(E e)
将指定元素插入此列表的开头。
void addLast(E e)
将指定元素添加到此列表的结尾。
E element()
获取但不移除此列表的头(第一个元素)。
E getFirst()
返回此列表的第一个元素。
E getLast()
返回此列表的最后一个元素。
E removeFirst()
移除并返回此列表的第一个元素。
E removeLast()
移除并返回此列表的最后一个元素。
boolean offer(E e)
将指定元素添加到此列表的末尾(最后一个元素)。
boolean offerFirst(E e)
在此列表的开头插入指定的元素。
boolean offerLast(E e)
在此列表末尾插入指定的元素。
E peek()
获取但不移除此列表的头(第一个元素)。
E peekFirst()
获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekLast()
获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
E poll()
获取并移除此列表的头(第一个元素)
E pollFirst()
获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast()
获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
E pop()
从此列表所表示的堆栈处弹出一个元素。
void push(E e)
将元素推入此列表所表示的堆栈。
4.测试
package cn.tedu.api;
import java.util.Arrays;
import java.util.LinkedList;
//测试 LinkedList
public class Test03_LinkedList {
public static void main(String[] args) {
//1.创建对象
LinkedList<Integer> list = new LinkedList();
//2.调用方法
//继承来的方法们
list.add(1);//添加元素
list.add(2);
list.add(2);
list.add(null);
System.out.println(list);
list.add(4,3);//在指定索引处添加元素
System.out.println(list);
list.addAll(list);//添加一个集合
System.out.println(list);
list.addAll(0,list);//在指定索引处添加集合
System.out.println(list);
//list.clear();//清除所有元素
//System.out.println(list);
System.out.println(list.contains(1));//判断是否包含某元素,包含返回true
System.out.println(list.get(3));//获取索引处的元素
System.out.println(list.indexOf(2));//获取2第一次出现的索引值
System.out.println(list.lastIndexOf(2));//获取2最后一次出现的索引值
list.remove(0);//移除0索引的元素
System.out.println(list);
list.remove((Integer)null);//移除null元素
System.out.println(list);
list.set(0,22222);//把索引为0的元素替换成2222
System.out.println(list);
System.out.println(list.size());//获取集合长度
Object[] obj = list.toArray();//把此集合中的元素存入Object[]中
System.out.println(Arrays.toString(obj));
//特有的方法们
list.addFirst(520);//添加首元素
System.out.println(list);
list.addLast(520);//添加尾元素
System.out.println(list);
System.out.println(list.getFirst());//获取首元素
System.out.println(list.getLast());//获取尾元素
list.removeFirst();//移除首元素
list.removeLast();//移除尾元素
System.out.println(list);
list.offer(520);//将指定元素添加在末尾
list.offerFirst(521);//添加首元素
list.offerLast(521);//添加尾元素
System.out.println(list);
System.out.println(list.peek());//获取首元素
System.out.println(list.peekFirst());//获取首元素
System.out.println(list.peekLast());//获取尾元素
System.out.println(list.poll());//获取并删除首元素
System.out.println(list.pollFirst());//获取并删除首元素
System.out.println(list.pollLast());//获取并删除尾元素
System.out.println(list);
}
}
六、set接口
1.概述
- Set接口也是Collection接口的子接口
- 能用父接口的所有方法
2.特点
--乱序
--不重复
--能存一个null
--没下标
3.常用方法
继承自Collection接口的
4.测试
package cn.tedu.api;
import java.util.*;
//测试 Set
public class Test04_Set {
public static void main(String[] args) {
//1.创建对象
Set<Integer> set = new HashSet();
//2.调用方法
set.add(1);
set.add(2);
set.add(null);
set.add(1);
set.add(3);
System.out.println(set);//特点:无序+通常用来给数据去重
set.addAll(set);
//set.clear();
System.out.println(set.contains(1));
System.out.println(set.containsAll(set));
System.out.println(set.equals(123));
System.out.println(set.hashCode());
System.out.println(set.isEmpty());
set.remove(1);
System.out.println(set);
//set.removeAll(set);
//System.out.println(set);
set.retainAll(set);
System.out.println(set);
System.out.println(set.size());
Object[] obj = set.toArray();
System.out.println(Arrays.toString(obj));
//迭代set迭代方式
//方式1:Iterator<E> iterator() --继承自父接口Collection的
Iterator<Integer> it = set.iterator();
while (it.hasNext()){//判断有没有元素
Integer in = it.next();//获取数据+后移指针
System.out.println(in);
}
//方式2:foreach -- foreach可以用在数组或者Collection集合中
for(Integer i : set){
System.out.println(i);
}
}
}
七、HashSet
1.概述
是Set接口的实现类,拥有set接口的所有特点和方法们
HashSet底层维护的是一个 哈希表/散列表
2.创建对象
HashSet()
构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
3.常用方法
lue
八、Map接口
1.概述
Map接口里的数据有格式上的要求.必须是一组 键值对 的形式.
Map<K,V> --其中,K是映射里的键,V是映射里的值
--而且K不能重复,V可以重复
Map.put(K,V);
2.特点
- 一个映射不能包含重复的键
- 每个键最多只能映射到一个值。
- 数据无序
3.常用方法
略
4.Map的原理
5.Map的迭代
6.测试
package cn.tedu.api;
import sun.security.action.PutAllAction;
import java.security.KeyStore;
import java.util.*;
//测试 map接口
public class Test01_Map {
public static void main(String[] args) {
//1.创建map对象 -- Map里的数据都是一组键值对数据,可以使用泛型约束K和V的类型
Map<Integer,String> map = new HashMap();
//2.调用方法
map.put(9527,"唐伯虎");//添加数据
map.put(9529,"秋香");
map.put(9528,"如花");
System.out.println(map);//{9527=唐伯虎, 9528=如花, 9529=秋香} -- 无序的数据,每组数据由K和V组成
//map.clear();//清楚map集合中的数据
//System.out.println(map);
System.out.println(map.containsKey(9528));//判断是否包含指定的key值
System.out.println(map.containsValue("如花"));//判断是否包含指定的value值
System.out.println(map.equals("如花"));//判断map集合是否与指定的集合相等
System.out.println(map.get(9527));//获取key值为9527的value值
System.out.println(map.hashCode());//返回集合的哈希码值
System.out.println(map.isEmpty());//判断集合是否为空
map.remove(9529);//移除集合中指定key值的映射关系
System.out.println(map);
System.out.println(map.size());//返回集合中的 键-值 映射关系数
Map<Integer,String> map1 = new HashMap();
map1.put(9530,"马尔扎哈");
map1.put(9531,"古力娜扎");
map.putAll(map1);//向指定映射关系的集合中加入一个新的映射关系的集合
System.out.println(map);
//迭代map集合的方法 -- 三种
/* 方式1:Set<K> keySet()
* 把map里的key存入set
* 迭代set,获取每个key
* 拿着key回map里找value
* */
Set<Integer> set =map.keySet();//把map里的key存入set
Iterator<Integer> it = set.iterator();
//迭代set,获取每个key
while (it.hasNext()){
Integer in = it.next();
String value = map.get(in);
if(value.equals("马尔扎哈")){
System.out.println(value+"来个微信!");
}
//拿着key回map里找value
System.out.println(in+"~~~~"+value);
}
/* 方式2:Set<Map.Entry<E,V>> entrySet()
* 把map里的key和value封装成一个Entry对象存入set
* 迭代set,获取每个Entry
* 获取Entry身上的key和value
* */
//把map里的key和value封装成一个Entry对象存入set
Set<Map.Entry<Integer,String>> set1 =map.entrySet();
//迭代set,获取每个Entry
for (Map.Entry<Integer,String> entry: set1){
//获取Entry身上的key和value
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"===="+value);
}
/* 方式3:Collection<V> values()
* 把map里的所有value获取出来,存入Collection里
* */
Collection<String> values=map.values();
System.out.println(values);
}
}
九、HashMap
1.创建对象
HashMap()
构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
2.常用方法
同Map接口
3.原理
HashMap中存放数据时,拿着你的数据,开始计算存储位置(拿着key哈希算法)
开始存:
1,这个位置是空的,没存过数据,把数据直接存入数组
2,这个位置存过了,有数据了(hash碰撞/hash冲突),就会形成链表结构(把新的数据,挂载在老数据的下面)
3,最好把数据都放在数组节点上.如果链表太长,会影响查询效率
4,影响HashMap的性能有两个因素:初始容量和加载因子
初始容量 是指是哈希表中桶的数量–就是数组的容量,默认是16
加载因子 是指哈希表在其容量自动增加之前可以达到多满的一种尺度,默认是0.75
当存储的数据容量超出阈值(16*0.75)后,会发生rehash的现象,会自动扩容,大概是原来容量的两倍.
尽量减少rehash的过程.因为需要底层再次开辟空间,初始化,赋值,复制等动作…
4.测试
package cn.tedu.api;
import java.util.*;
//测试 HashMap
public class Test02_Map {
public static void main(String[] args) {
//1.创建HashMap对象
//低层创建了一个Entry[],默认容量为16,默认加载因子是0.75
Map<Integer, String> map = new HashMap();
//2.调用方法
map.put(1001,"马尔扎哈");
map.put(1002,"古力娜扎");
map.put(1003,"迪丽热巴");
System.out.println(map);
Map<Integer,String> map1 = new HashMap<>();
map1.put(2001,"格雷福斯");
map1.put(2002,"赫卡里姆");
map1.put(2003,"格里菲斯");
map.putAll(map1);
System.out.println(map);
//map.clean();
map.remove(2003);
map.remove(2001);
System.out.println(map);
System.out.println(map.containsKey(2001));
System.out.println(map.containsValue("赫卡里姆"));
System.out.println(map.get(1001));
System.out.println(map.isEmpty());
System.out.println(map.size());
//迭代Map集合的方法
Set<Integer> set = map.keySet();
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.println(key+"~~~~"+value);
}
Set<Map.Entry<Integer,String>> set1=map.entrySet();
for (Map.Entry<Integer,String> e:set1){
Integer key = e.getKey();
String value = e.getValue();
System.out.println(key+"===="+value);
}
Collection<String> value = map.values();
System.out.println(value);
}
}
5.练习
统计字符串中字符的出现次数
package cn.tedu.api;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
//练习 统计字符串中字符的出现次数
public class Test03_Map {
public static void main(String[] args) {
//1.接收用户输入的字符串
System.out.println("请输入一串字符串:");
String str = new Scanner(System.in).nextLine();
//2.定义Map,准备存储数据,类似于a=1,b=2,c=1
//其中key就是a,b,c value就是 1 2 1这样的数据
Map<Character,Integer> map = new HashMap<>();
//3.遍历字符串,得到每个字符
for(int i =0;i<str.length();i++){
//根据下标i获取字符
char key = str.charAt(i);
//4.根据key的值去map里面查value
Integer value = map.get(key);//每个字符第一次查出来都是null--Integer是引用类型,应用类型的默认值是null
if(value == null){//没存过,就是默认值null
map.put(key,1);
}else{//存过了
map.put(key,value+1);//在原来的值上加一
}
}
System.out.println(map);
}
}
十、集合的工具类Collections
1.概述
Collections专门用来给Collection集合服务
2.常用方法
static <T> boolean addAll(Collection c, T... elements)
将所有指定元素添加到指定 collection 中。
static max(Collection<? extends T> coll)
根据元素的自然顺序,返回给定 collection 的最大元素。
static min(Collection<? extends T> coll)
根据元素的自然顺序 返回给定 collection 的最小元素。
static void reverse(List<?> list)
反转指定列表中元素的顺序。
static void sort(List<T> list)
根据元素的自然顺序 对指定列表按升序进行排序。
static void swap(List<?> list, int i, int j)
在指定列表的指定位置处交换元素。
3.测试
package cn.tedu.api;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//测试 集合工具类Collections
public class Test04_Collections {
public static void main(String[] args) {
//1.给list集合添加十个元素
List<Integer> list = new ArrayList();
Collections.addAll(list,1,3,2,8,5,6,7,4,9,10);//向集合中一次性加入多个元素
System.out.println(list);
System.out.println(Collections.max(list));//求集合中的最大值
System.out.println(Collections.min(list));//求集合中的最小值
Collections.sort(list);//对集合进行排序
System.out.println(list);
Collections.reverse(list);//对集合进行倒序
System.out.println(list);
Collections.swap(list,9,0);//对集合中固定的两个索引处的值进行置换
System.out.println(list);
}
}
拓展
1.了解 字符流的按行 读写数据
参考网页版笔记的1.10.5读一行写一行
2.IO NIO AIO
- IO:面向流、同步、阻塞
- 在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。
- NIO:面向缓冲、同步、非阻塞
- 提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。
- AIO(NIO2):面向缓冲、异步、非阻塞
- 是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。但目前还不够成熟,应用不多。
3.list的练习
–统计list集合中,元素出现的次数
package cn.tedu.api;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
//统计list集合中,元素出现的次数
public class Test05_ListTest {
public static void main(String[] args) {
//创建对象
List<Integer> list = new ArrayList();
//接收用户输入的数据
System.out.println("请输入十个整数:");
Scanner num = new Scanner(System.in);
//将用户输入的数据存入集合中
for(int i = 0;i<10;i++){
list.add(i,num.nextInt());
}
//提示集合中的数据
//System.out.println(list);
//对集合进行个排序
int temp = 0;
for(int i = 0;i<list.size();i++){
for(int j =i+1;j<list.size();j++){
if(list.get(i)>list.get(j)){
temp = list.get(i);
list.set(i,list.get(j));
list.set(j,temp);
}
}
}
System.out.println(list);//显示排序后的集合
method(list);//递归统计每个数字出现的次数
}
//递归 判断出现的次数
private static void method(List list){
for(int i = 0;i<list.size()-1;i++){
if(list.get(i)!=list.get(i+1)){
System.out.println(list.get(i)+"出现了"+(i+1)+"次");
method(list.subList(i+1,list.size()));
break;
}
}
// System.out.println(list);
}
}
–向list中添加随机数,但是不能重复
package cn.tedu.api;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
//向list中添加随机数,但是不能重复
public class Test06_ListTest {
public static void main(String[] args) {
//1.创建集合
List<Integer> list = new LinkedList();
//2.创建随机数并赋值给集合
for(int i=0;i<10;i++){
int r = new Random().nextInt(10);//0~9
if(!list.contains(r)){
list.add(r);
}
}
System.out.println(list);
}
}
4.面试题:iterator() 和 listIterator()的区别?
iterator()来自父接口Collection/listIterator()是List子接口特有的
返回值不同,Iterator是父接口/ListIterator是子接口,子接口能用所有父接口的功能,而且拓展了逆向遍历的方法 们~~~
1)iterator()
//方式1:Iterator<E> iterator() -- 继承自Collection接口方法
Iterator<Integer> it=list.iterator();
while(it.hasNext()){//hasNext() 用来判断
Integer in=it.next();//next()用来获取数据并把指针后移
System.out.println(in+"::::1");
}
2)listIterator()
//方式2:ListIterator<E> listIterator()
ListIterator<Integer> it2 = list.listIterator();
while (it2.hasNext()){//hasNext()用来判断后面有没有元素
Integer in=it2.next();//next()获取后面的一个元素
System.out.println(in);
}
//逆向遍历 -- 前提是:必须先顺序遍历 -- 不用!!
while (it2.hasPrevious()){//判断前面有元素吗
Integer in=it2.previous();//获取前面的一个元素
System.out.println(in);
}
5.ArrayList的原理
- 底层以Object[]实现,是一个连续的空间,适合查询
6.ArrayList和LinkedList的区别
-
ArrayList低层是一个数组,是一个连续的空间,适合查询
-
LinkedList低层是一个链表,空间不连续,适合增删
7.集合的几种迭代方法(必须记住)
–Collection集合的迭代方法:如下
7.Iterator迭代器
7.1迭代器的作用
迭代器是帮助Collection集合遍历元素的。
7.2迭代器如何获取
Collection集合有这个方法:
方法 说明 Iterator iterator() 获取迭代器对象 7.3迭代器常用方法
- Iterator接口常用的有两个方法:
方法 说明 E next() 获取集合中的元素 boolean hasNext() 判断集合中有没有下一个元素 void remove() 删除当前元素
Iterator迭代器
判断集合中有没有元素,有的话取出来,继续判断,有的话再取出,这种称为迭代。
使用步骤:
1:使用集合中的方法Iterator()获取迭代器的实现类对象,使用Iterator对象接收。
2:使用Iterator接口中的方法hasNext判断还有没有下一个元素。
3:使用Iterator接口中的方法next取出集合中下一个元素。
方法1:由迭代器Iterator进行遍历
Iterator it = c.iterator();
while (it.hasNext()) {//使用Iterator接口中的方法hasNext判断还有没有下一个元素。
Object o = it.next();//使用Iterator接口中的方法next取出集合中下一个元素。
System.out.println(o);
}
–List集合的四种迭代方法:如下
方法1:由迭代器Iterator进行遍历
//方式1:继承来的Iterator<E> iterator()
Iterator<Integer> it = list.iterator();
while (it.hasNext()){//判断有没有元素
Integer data = it.next();//获取元素
System.out.println(data);//打印元素
}
方法2:根据迭代器Iterator遍历的形式 来迭代ListIterator进行遍历
//方式2:自己扩展的ListIterator<E> listIterator()
ListIterator<Integer> it2 = list.listIterator();
//正向迭代
while(it2.hasNext()){//判断后面有元素吗
Integer data = it2.next();//获取后面的元素
System.out.println(data);
}
方法3:根据索引遍历for(int i = 0;i < list.size();i++)
//方式3:根据下标迭代
for (int i = 0; i < list.size(); i++) {
//根据下标获取元素
Integer data = list.get(i);
System.out.println(data);
}
方法4:由集合定义时的泛型遍历for(T t:list)—>实际上就是foreach
//方式4:增强for循环/foreach循环
//语法:for(得到的数据的类型 变量名 : 循环的容器){}
//使用场景:数组 | Collection集合
//缺点:没法根据下标操作具体元素
for(Integer a : list){
System.out.println(a);
}
–map集合的三种迭代方法:如下
方法1:
方法2:
方法3:
–set集合的两种迭代方法:如下
方法1:
方法2:
8.数组和集合的区别
未
完
待
续