Java的集合相关知识
集合
引入集合
当我们需要将一些相同结构的个体整合在一起时,就可以考虑使用集合了。比如:新闻列表,购物车等。
集合和数组的对比
-
集合和数组的相似点
- 都可以存储多个对象,对外作为一个整体存在
-
数组的缺点
- 长度必须在初始化的时候指定,且固定不变
- 数组采用连续存储空间。删除和添加效率低下
- 数组无法直接保存映射关系
- 数组缺乏封装,操作繁琐
集合框架
- Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中,存放在集合中的数据,被称为元素(element)。
- 集合框架
- Collection接口存储一组不唯一,无序的对象
- List接口存储一组不唯一,有序(索引顺序)的对象
- Set接口存储一组唯一,无序的对象
- Map接口存储一组键值对象,提供key到value的映射
- Key唯一 无序
- value 不唯一 无序
泛型
泛型是(Generics)JDK1.5 的一个新特性,通常用来和集合对象一起使用,它是程序的增强器,它是目前主流的开发方式。
package com.cnblogs;
import java.util.*;
/*
本类用于测试泛型的优点1
*/
public class TestGeneric1 {
public static void main(String[] args) {
/*
泛型的出现,是想要模拟数组数据类型检查的功能
数组的好处:在编译时期就检查数据的类型,只要不是规定的类型,就会在编译器中报错,不需要运行程序就可以看到
*/
String[] arr = new String[5];
/*
泛型通常与集合一起使用
*/
List list = new ArrayList();//需要导包
list.add("柒");
list.add(1);
list.add(1.5);
/*
引入泛型,主要是想通过泛型来约束集合中元素的类型<?>
泛型的好处,可以把报错的时机提前,在编译期就报错,而不是运行以后才抛出异常,在向集合添加元素时
会先检查元素的类型,不是要求的类型就编译失败
*/
List<String> list2 = new ArrayList<String>();
list2.add("柒");
// list2.add(1); 报错
/*
<type> type的值需要查看要存放的类型是什么,根据业务类型自定义,
但type必须是引用类型,不可能是基本类型
*/
List<Integer> list3 = new ArrayList<Integer>();
// List<Integer> list3 = new ArrayList<>(); 可以
// List<Integer> list3 = new ArrayList(); 可以
list3.add(100);
list3.add(101);
list3.add(102);
System.out.println(list3);//[100, 101, 102]
}
}
package com.cnblogs;
/*
本类用于测试泛型的优点2
*/
public class TestGeneric2 {
public static void main(String[] args) {
//需求:分别打印3个数组中的所有元素
Integer[] a = {1,2,3,4,5,6,7};
print(a);
String[] b = {"大哥","二哥","三哥","四哥","五哥","六哥","七弟",};
print(b);
Double[] c = {6.0,6.6,6.66,6.666,6.6666,6.66666,6.666666};
print(c);
}
/*
泛型方法:
可以写出更加通用的方法,E表示Element元素
语法:必须两处同时出现:一个是方法参数类型是泛型
另一个是返回值类型前的泛型,两处一起表示这是一个泛型方法
*/
private static <E> void print(E[] a) {
//我们可以通过for循环遍历输出数组的每一个元素
for(E x : a){
System.out.println(x);
}
}
// private static void print(Integer[] a) {
// //我们可以通过for循环遍历输出数组的每一个元素
// for(Integer x : a){
// System.out.println(x);
// }
// }
// /*
// 增强for循环:只需要对数据从头到尾的遍历一次时使用
// 好处:比普通for循环的语法简单,效率高
// 缺点:无法按照下标来操作元素,只能从头到尾遍历
// 语法:for(2 3 : 1){循环体}
// 1.你需要遍历的数据
// 2.遍历得到的具体元素类型
// 3.遍历得到元素的名字
// */
// private static void print(String[] b) {
// for (String x: b) {
// System.out.println(x);
// }
// }
// private static void print(Double[] c) {
// for (Double x: c) {
// System.out.println(x);
// }
// }
}
Collection
package com.cnblogs;
import java.util.*;
/*
本类用于测试Collection接口
*/
public class TestCollection {
public static void main(String[] args) {
/*
<Integer>是泛型,用来约束集合中的数据类型,不能是基本类型,必须为引用类型
*/
Collection<Integer> c = new ArrayList<>();
//添加元素
c.add(100);
c.add(200);
c.add(300);
c.add(400);
c.add(500);
c.add(600);
c.add(700);
// c.clear(); //清空当前集合
//获取哈希码
System.out.println(c.hashCode());
System.out.println(c.toString());//打印集合的具体元素 重写了
System.out.println(c.equals(200));//false
System.out.println(c.contains(200));//true c中是否含有指定元素200
System.out.println(c.isEmpty());//判断集合是否为空 false
System.out.println(c.remove(100));//移除集合中的指定元素,成功返回true
System.out.println(c.size());//6 返回集合的元素个数
Object[] arr = c.toArray();//将指定的集合转为数组
System.out.println(Arrays.toString(arr));//[200, 300, 400, 500, 600, 700]
Collection<Integer> c2 = new ArrayList<>();
c2.add(2);
c2.add(4);
c2.add(6);
System.out.println(c2);
c.addAll(c2);//c2集合追加到c的末尾,c2本身不变
System.out.println(c);
System.out.println(c2);
System.out.println(c.containsAll(c2));//true 当前集合是否包含指定集合中的所有元素
System.out.println(c);//[200, 300, 400, 500, 600, 700, 2, 4, 6]
System.out.println(c.removeAll(c2));//true 删除c中c2的所有元素
System.out.println(c);//[200, 300, 400, 500, 600, 700]
System.out.println(c2);//[2, 4, 6]
c.add(6);
System.out.println(c.retainAll(c2));//true 去除除了c2中的所有内容(交集)
System.out.println(c);//[6]
/*
迭代集合/遍历集合:
1.获取集合的迭代器 c.iterator();
2.判断集合中是否有下一个可迭代元素 it.hasNext();
3.获取当前迭代到的元素 it.next();
*/
Iterator<Integer> it = c.iterator();
while (it.hasNext()){
Integer num = it.next();
System.out.println(num);//6
}
}
}
List
package com.cnblogs;
import java.util.*;
/*
本类用于测试list接口
*/
public class TestList {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("大娃");
list.add("二娃");
list.add("三娃");
list.add("四娃");
list.add("五娃");
list.add("六娃");
list.add("柒娃");
System.out.println(list);
//测试继承自Collection的方法
// list.clear();清空集合
// System.out.println(list.contains("张三"));//false
// System.out.println(list.equals("大娃"));//false
// System.out.println(list.isEmpty());//false
// System.out.println(list.remove("三娃"));
// System.out.println(list.size());//7
//测试List自己的方法
list.add("张三");//追加在最后
list.add(1,"李四");//索引从0开始
list.add(3,"张三");
System.out.println(list);
System.out.println(list.indexOf("张三"));//第一次出现的索引 3
System.out.println(list.lastIndexOf("张三"));//最后一次出现的索引 9
System.out.println(list);
System.out.println(list.remove(5));//四娃 删除指定元素并返回
System.out.println(list.get(3));//张三
System.out.println(list);
list.set(8,"王二麻子");
System.out.println(list);
//测试集合间的操作
List<String> list2 = new ArrayList<>();
list2.add("1");
list2.add("2");
list2.add("3");
list2.add("4");
list2.add("5");
list2.add("6");
System.out.println(list2);
// System.out.println(list.addAll(list2));//true
// System.out.println(list);//[大娃, 李四, 二娃, 张三, 三娃, 五娃, 六娃, 柒娃, 王二麻子, 1, 2, 3, 4, 5, 6]
list.addAll(1,list2);
System.out.println(list);//[大娃, 1, 2, 3, 4, 5, 6, 李四, 二娃, 张三, 三娃, 五娃, 六娃, 柒娃, 王二麻子]
System.out.println(list.containsAll(list2));//true
System.out.println(list.removeAll(list2));//移除list中list2的所有元素
System.out.println(list);//[大娃, 李四, 二娃, 张三, 三娃, 五娃, 六娃, 柒娃, 王二麻子]
}
}
package com.cnblogs;
import java.util.*;
/*
本类用于测试List的接口2
*/
public class TestList2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王二麻子");
list.add("路人甲");
list.add("宋兵乙");
list.add("炮灰丙");
list.add("土匪丁");
//迭代集合
//方法一
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
System.out.println();
//方法二
for (String x : list){
System.out.print(x);
}
System.out.println();
//方法三
Iterator<String> it = list.iterator();
while (it.hasNext()){
String str = it.next();
System.out.print(str);
}
System.out.println();
//方法四
/*
listIterator 是List特有的迭代器
Iterator<E> -- 父接口 hasNext() next()
listIterator<E> -- 子接口 有自己的特有功能,逆序遍历,添加元素等,不常用
public interface ListIterator<E>extends Iterator<E>
*/
ListIterator<String> it2 = list.listIterator();
while(it2.hasNext()){
System.out.print(it2.next());
}
}
}
ArrayList
package com.cnblogs;
import java.util.*;
/*
本类用于ArrayList相关测试
*/
public class TestArrayList {
public static void main(String[] args) {
/*
底层会自动帮我们创建数组来存放对象,初始长度为10
*/
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
list.add(400);
list.add(500);
list.add(600);
list.add(700);
System.out.println(list);
// list.clear();
// System.out.println(list);
System.out.println(list.contains(100));//true
System.out.println(list.contains("100"));//false
System.out.println(list.isEmpty());//false
System.out.println(list.get(0));//100
System.out.println(list.indexOf(400));//3
System.out.println(list.lastIndexOf(400));//4
System.out.println(list.remove(1));//200
System.out.println(list);//[100, 300, 400, 400, 500, 600, 700]
System.out.println(list.remove(Integer.valueOf(300)));
System.out.println(list);//[100, 400, 400, 500, 600, 700]
// System.out.println(list.remove(300));
/*
上面会报错,数组下标越界,如果传入300会认为是int类型的索引,所有,如果想要删除指定元素
需要手动把300装箱成Integer类型
*/
System.out.println(list.remove(Integer.valueOf(400)));
System.out.println(list);//[100, 400, 500, 600, 700]
System.out.println(list.set(2,888));//500
System.out.println(list);//[100, 400, 888, 600, 700]
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
System.out.println();
for(Integer x : list){
System.out.print(x);
}
System.out.println();
Iterator<Integer> it = list.iterator();
while (it.hasNext()){
System.out.print(it.next());
}
System.out.println();
ListIterator<Integer> it2 = list.listIterator();
while (it2.hasNext()){
System.out.print(it2.next());
}
}
}
LinkedList
package com.cnblogs;
import java.util.*;
/*
本类用于LinkedList的相关测试
*/
public class TestLinkedList {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("孙悟空");
list.add("猪八戒");
list.add("沙和尚");
list.add("唐玄奘");
list.add("白龙马");
System.out.println(list);
list.addFirst("玉兔精");
list.addLast("孔雀精");
System.out.println(list);//[玉兔精, 孙悟空, 猪八戒, 沙和尚, 唐玄奘, 白龙马, 孔雀精]
System.out.println(list.getFirst());//玉兔精
System.out.println(list.getLast());//孔雀精
System.out.println(list.removeFirst());//玉兔精
System.out.println(list.removeLast());//孔雀精
System.out.println(list);//[孙悟空, 猪八戒, 沙和尚, 唐玄奘, 白龙马]
LinkedList<String> list2 = new LinkedList<>();
list2.add("水浒传");
list2.add("西游记");
list2.add("三国演义");
list2.add("红楼梦");
System.out.println(list2);//[水浒传, 西游记, 三国演义, 红楼梦]
System.out.println(list2.element());//水浒传 获取但不移除首元素
System.out.println(list2);//[水浒传, 西游记, 三国演义, 红楼梦]
/*
查询系统
*/
System.out.println(list2.peek());//水浒传 获取但不移除首元素
System.out.println(list2.peekFirst());//水浒传 获取但不移除首元素
System.out.println(list2.peekLast());//红楼梦 获取但不移除尾元素
/*
新增
*/
System.out.println(list2.offer("聊斋"));
System.out.println(list2);//[水浒传, 西游记, 三国演义, 红楼梦, 聊斋]
System.out.println(list2.offerFirst("斗罗大陆"));
System.out.println(list2.offerLast("斗破苍穹"));
System.out.println(list2);//[斗罗大陆, 水浒传, 西游记, 三国演义, 红楼梦, 聊斋, 斗破苍穹]
/*
移除
*/
System.out.println(list2.poll());//斗罗大陆
System.out.println(list2);//[水浒传, 西游记, 三国演义, 红楼梦, 聊斋, 斗破苍穹]
System.out.println(list2.pollFirst());//水浒传
System.out.println(list2.pollLast());//斗破苍穹
System.out.println(list2);//[西游记, 三国演义, 红楼梦, 聊斋]
}
}
Map
package com.cnblogs;
import java.util.*;
/*
本类用于测试map接口
*/
public class TsetMap {
public static void main(String[] args) {
/*
Map中的数据要符合映射规则,一定要同时指定k和v的数据类型
至于k和v取什么类型取决于具体的业务需求
*/
Map<Integer,String> map = new HashMap<>();
map.put(1,"张三");
map.put(2,"李四");
map.put(3,"王二麻子");
map.put(4,"路人甲");
map.put(996,"宋兵乙");
map.put(997,"宋兵乙");
System.out.println(map);//{1=张三, 2=李四, 3=王二麻子, 4=路人甲, 996=宋兵乙, 997=宋兵乙}
map.put(1,"炮灰丙");
System.out.println(map);//{1=炮灰丙, 2=李四, 3=王二麻子, 4=路人甲, 996=宋兵乙, 997=宋兵乙}
/*
map中存放着的都是无序数据,map中的value可以重复-比如可以写两个宋兵乙
map中key不可以重复,重复了后面的value会覆盖前面的value,炮灰丙覆盖了张三
*/
//方法测试
// map.clear();//清空集合
System.out.println(map.hashCode());//1013219698
System.out.println(map.equals("土匪丁"));//false
System.out.println(map.isEmpty());//false
System.out.println(map.size());//6
//判断集合是否包含指定的键
System.out.println(map.containsKey(996));//true
System.out.println(map.containsKey(900));//false
//判断集合是否包含指定的value值
System.out.println(map.containsValue("张三"));//false
System.out.println(map.containsValue("炮灰丙"));//true
//根据key值来获取对应的value值
System.out.println(map.get(996));//宋兵乙
//删除此key值对应的键值对 k和v
System.out.println(map.remove(997));//宋兵乙
System.out.println(map);//{1=炮灰丙, 2=李四, 3=王二麻子, 4=路人甲, 996=宋兵乙}
Collection<String> values = map.values();
System.out.println(values);//[炮灰丙, 李四, 王二麻子, 路人甲, 宋兵乙]
Set<Integer> integers = map.keySet();
System.out.println(integers);//[1, 2, 3, 4, 996]
//map集合的迭代方式
/*
方式一:遍历map中的数据,但是map本身没有迭代器,所以需要先转换成set集合
Set<key>:把map中的所有key值存入到set集合当中--keySet()
*/
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.print("{" + key + "=" + value + "}");//{1=炮灰丙}{2=李四}{3=王二麻子}{4=路人甲}{996=宋兵乙}
}
System.out.println();
/*
方式二:遍历map集合需要先把map集合转成set集合,是把map中的一对键值k和v作为一个Entry<k,v>
整体放入set,一对K,V就是一个Entry
*/
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> it2 = entrySet.iterator();
while (it2.hasNext()){
Map.Entry<Integer, String> entry = it2.next();
Integer key = entry.getKey();
String value = entry.getValue();
System.out.print("{" + key + "=" + value + "}");//{1=炮灰丙}{2=李四}{3=王二麻子}{4=路人甲}{996=宋兵乙}
}
}
}
package com.cnblogs;
import java.util.*;
/*
本类用于字符串中字符个数的统计案例
*/
public class TestMap2 {
/*
用户输入:abcccc
输出结果{a = 1,b = 1,c = 4}
*/
public static void main(String[] args) {
System.out.println("请输入要统计的字符串:");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
/*
统计的是每个字母出现的次数,单个字母是char类型 --> Character
Integer统计的是字母出现的次数,可以重复,不能作为key
*/
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < input.length(); i++) {
char key = input.charAt(i);
//统计次数
Integer value = map.get(key);
if(value == null){
map.put(key,1);
}else{
map.put(key,value + 1 );
}
}
System.out.println(map);
// Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
// Iterator<Map.Entry<Character, Integer>> it = entrySet.iterator();
// while (it.hasNext()){
// Map.Entry<Character, Integer> entry = it.next();
// Character key = entry.getKey();
// Integer value = entry.getValue();
// System.out.print("{" + key + "=" + value + "}");
// }
Set<Character> keySet = map.keySet();
Iterator<Character> it2 = keySet.iterator();
while(it2.hasNext()){
Character key = it2.next();
Integer value = map.get(key);
System.out.print("{" + key + "=" + value + "}");
}
scanner.close();
}
}
Set
package com.cnblogs;
import java.util.*;
public class TestSet {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("路人甲");
set.add("宋兵乙");
set.add("炮灰丙");
set.add("土匪丁");
set.add("土匪丁");
System.out.println(set);//[炮灰丙, 土匪丁, 路人甲, 宋兵乙] 没有顺序,元素不能重复
set.add(null);//存入null值
set.add(null);
set.add("null");//存入字符串null
System.out.println(set);//[null, 炮灰丙, null, 土匪丁, 路人甲, 宋兵乙] 只能有一个null值
/*
自定义对象,如果想要去重,需要重写hashCode()和equals()方法
*/
}
}
package com.cnblogs;
import java.util.*;
public class TestSet2 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("路人甲");
set.add("宋兵乙");
set.add("炮灰丙");
set.add("土匪丁");
set.add("土匪丁");
set.add(null);
set.add("null");
System.out.println(set);//[null, 炮灰丙, null, 土匪丁, 路人甲, 宋兵乙]
// set.clear();
System.out.println(set.hashCode());//112899594
System.out.println(set.equals("皮卡丘"));//false
System.out.println(set.contains("张三"));//false
System.out.println(set.isEmpty());//false
System.out.println(set.remove(null));//true
System.out.println(set.remove("null"));//true
System.out.println(set);//[炮灰丙, 土匪丁, 路人甲, 宋兵乙]
System.out.println(set.size());//4
Object[] arr = set.toArray();
System.out.println(Arrays.toString(arr));//[炮灰丙, 土匪丁, 路人甲, 宋兵乙]
//集合间的操作
Set<String> set2 = new HashSet<>();
set2.add("张三");
set2.add("李四");
set2.add("王二麻子");
System.out.println(set2);//[李四, 张三, 王二麻子]
System.out.println(set.equals(set2));//false
System.out.println(set.addAll(set2));//true
System.out.println(set);//[李四, 张三, 炮灰丙, 王二麻子, 土匪丁, 路人甲, 宋兵乙]
System.out.println(set.containsAll(set2));//true
System.out.println(set.removeAll(set2));//true
System.out.println(set);//[炮灰丙, 土匪丁, 路人甲, 宋兵乙]
//retainAll 取交集存入set中
set.add("张三");
System.out.println(set.retainAll(set2));//true
System.out.println(set);//[张三]
Iterator<String> it = set2.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");//李四 张三 王二麻子
}
}
}