前言
容器就是能装对象的对象;
由于List、Set、Map这3个接口,向上都实现了1个Collection接口,我把3者统称为集合数据类型;
一、List容器
Java的ArryList等价于Python中的List,它是线性数据结构,相对于Arry数组来说是可变长的。
List向上实现了Collection接口,向下有2个实现类,分别是ArrayList和LinkedList,两者形成优势互补,使用方法一致。
1.ArrayList(列表)
ArrayList的内存是连续的,方便我们查询和遍历,但是不利于修改数据。
package Sets; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestList { public static void main(String[] args) { //列表 List arrayList = new ArrayList(); arrayList.add("老北京"); arrayList.add("双胞胎"); arrayList.add("六丁目"); arrayList.add("康师傅"); //[老北京, 双胞胎, 六丁目, 康师傅] System.out.println(arrayList); //链表 List likedList = new LinkedList(); likedList.add("老北京"); likedList.add("双胞胎"); likedList.add("六丁目"); likedList.add("康师傅"); //[老北京, 双胞胎, 六丁目, 康师傅] System.out.println(likedList); } }
2.LinkedList(链表)
链表的内存是不连续的,链表的优势是利于删除和新增数据,但是不利于数据遍历和查询(从头开始找到下一个,在到下一个.....)。
3.常用操作
列表(List)和链表(LikedList)都实现了List接口,所以2者可以调用的方法是一致的。
package Sets; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestList { public static void main(String[] args) { //列表 //添加元素 List list = new ArrayList(); list.add("老北京"); list.add("双胞胎"); list.add("六丁目"); list.add("康师傅"); list.add(1); //[老北京, 双胞胎, 六丁目, 康师傅] System.out.println(list); //删除元素 list.remove("康师傅"); System.out.println(list); //查看列表的长度 System.out.println(list.size()); //获取单个值:在list中任何元素都属于Object类型,但是我们使用值时需要强转 Object item2 = list.get(2); System.out.println((String) item2); //向下转型 Object item3 = list.get(3); System.out.println((int) item3); //向下转型 //成员关系判断等价于python中的in System.out.println(list.contains(1)); System.out.println(list.contains("康帅傅")); //变量列表 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } }
二、Set集合
从功能上来说Java中的Set集合等同于Python中的set,相较于List来说,set天然去重,没有重复的元素;
package Sets; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; public class TestSet { public static void main(String[] args) { Set set = new HashSet(); set.add("CS"); set.add("DNF"); set.add("LOL"); set.add("CS"); //Set天然去重,重复的数据是添加不进去的 //[CS, LOL, DNF] System.out.println(set); //TreeSet:会自动对集合中元素进行排序,而HashSet不会。 Set treeSet = new TreeSet(); treeSet.add(10); treeSet.add(102); treeSet.add(200); //[10, 102, 200] System.out.println(treeSet); } }
1.HashSet
元素不重复并且是无序的;
2.TreeSet
TreeSet除了对集合内的元素进行去重之外,还会对内部元素进行自动排序;
//TreeSet:会自动对集合中元素进行排序,而HashSet不会。 Set treeSet = new TreeSet(); treeSet.add(10); treeSet.add(102); treeSet.add(200); //[10, 102, 200] System.out.println(treeSet);
3.常用方法
HashSet和TreeSet都实现Set接口,所以2者能调用的方法也是一致的。
package Sets; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import java.util.HashSet; public class TestSet { public static void main(String[] args) { Set set = new HashSet(); set.add("CS"); set.add("DNF"); set.add("LOL"); set.add("CS"); //Set天然去重,重复的数据是添加不进去的 set.add(120); //Int--->Integer //[CS, LOL, DNF] //查看Set集合的长度 System.out.println(set.size()); //删除元素 set.remove("DNF"); System.out.println(set); //成员关系判断 System.out.println(set.contains("LOL")); } }
三、Map集合
Map相当于Python中的dict字典,用于存储key、value键值对。
1.HashMap
HashMap是无序的,但查询效率高。
//1.HashMap:无序的 Map map = new TreeMap(); map.put("zay", "周杰伦"); map.put("wf", "汪峰"); map.put("tz", "陶喆"); map.put("zbc", "周笔畅"); //{tz=陶喆, wf=汪峰, zay=周杰伦, zbc=周笔畅} System.out.println(map);
2.TreeMap
TreeMap是有序的,但查询效率地。
//2.TreeMap:TreeMap会自动根据key排序 Map map1 = new TreeMap(); map1.put(11, "周杰伦"); map1.put(22, "蔡徐坤"); map1.put(33, "六小灵通"); map1.put(44, "汪峰"); //{11=周杰伦, 22=蔡徐坤, 33=六小灵通, 44=汪峰} System.out.println(map);
3.常用操作
HashMap和TreeMap都实现了Map类,所以两者可调用的方法也一致;
package Sets; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; public class TestMap { public static void main(String[] args) { //Map集合 //1.HashMap:无序的 Map map = new TreeMap(); map.put("zay", "周杰伦"); map.put("wf", "汪峰"); map.put("tz", "陶喆"); map.put("zbc", "周笔畅"); //{tz=陶喆, wf=汪峰, zay=周杰伦, zbc=周笔畅} System.out.println(map); //2.TreeMap:TreeMap会自动根据key排序 Map map1 = new TreeMap(); map1.put(11, "周杰伦"); map1.put(22, "蔡徐坤"); map1.put(33, "六小灵通"); map1.put(44, "汪峰"); //{11=周杰伦, 22=蔡徐坤, 33=六小灵通, 44=汪峰} System.out.println(map); //3.常用操作 //Map获取value System.out.println(map1.get(11)); //Map删除数据 map1.remove(22); System.out.println(map1); //Map的长度 System.out.println(map1.size()); //Map-Key成员关系判断 System.out.println(map1.containsKey(11)); //Map-Value成员关系判断 System.out.println(map1.containsValue("周杰伦")); //Map覆盖Value map1.put(11, "只因你太美"); System.out.println(map1);//{11=只因你太美, 33=六小灵通, 44=汪峰} //Map获取所有的keys System.out.println(map1.keySet()); //[11, 33, 44] } }
4.练习
package Sets; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class TestPractice { public static void main(String[] args) { //预设敏感词汇 List badWords = new ArrayList(); badWords.add("苍井空"); badWords.add("武藤兰"); badWords.add("波多野结衣"); badWords.add("仓木麻衣"); badWords.add("麻生希"); //输入关键词 Scanner sc = new Scanner(System.in); System.out.print("请输入关键词: "); String keyWord = sc.next().trim(); //检查敏感词 if (badWords.contains(keyWord)) { //替换敏感词 keyWord = String.format("%s老师", keyWord.charAt(0)); } for (int i = 0; i < badWords.size(); i++) { String improperWord = (String) badWords.get(i); if (keyWord.contains(improperWord)) { String replacedStringg = ""; for (int j = 0; j < improperWord.length(); j++) { replacedStringg += "*"; } String replacedWord = keyWord.replace(improperWord, replacedStringg); keyWord = replacedWord; } } System.out.println(keyWord); } }
四、迭代集合
在Python中我们可以使用for循环遍历一切可迭代对象;
那么在Java中我们如何遍历set集合,这种没有索引的非线性数据类型呢?
我们也可以把Set、List转换成1个迭代器进行迭代获取值,从而达到遍历的目的。
1.迭代List
package Sets; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class TestIter { public static void main(String[] args) { List list = new ArrayList(); list.add("蔡徐坤"); list.add("吴亦凡"); list.add("李易峰"); list.add("鹿晗"); System.out.println(list); //for循环遍历 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } //List转换成1个迭代器 Iterator it = list.iterator(); System.out.println(it.next()); //第1个 System.out.println(it.next());//下1个 System.out.println(it.next());//下1个 System.out.println(it.next());//下1个 // System.out.println(it.next()); //没有元素了就抛出异常 //迭代器循环List while (it.hasNext()){ System.out.println(it.next()); } } }
2.迭代Set
package Sets; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class IterSet { public static void main(String[] args) { Set set = new HashSet(); set.add("小坤坤"); set.add("小凡凡"); set.add("小憨憨"); set.add("小峰峰"); //创建1个迭代器:既然Set是没有索引的,那我们创建1个迭代器 Iterator it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
3.迭代Map
package Sets; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class IterMap { public static void main(String[] args) { Map maping = new HashMap(); maping.put("太尉", "高俅"); maping.put("高衙内", "高坎"); maping.put("禁军教头", "王进"); maping.put("鲁提辖", "鲁达"); System.out.println(maping); //方案一:通过把map的keys转换成Iteratore遍历字典 Set set = maping.keySet(); Iterator it = set.iterator(); while (it.hasNext()) { String key = (String) it.next(); System.out.printf("%s<-->%s\n", key, maping.get(key)); } //方案二:entrySet()遍历字典 Set set1 = maping.entrySet(); Iterator it1 = set1.iterator(); while (it1.hasNext()) { Map.Entry entry = (Map.Entry) it1.next(); System.out.printf("%s《===》%s\n", entry.getKey(), entry.getValue()); } } }
五、泛型
Java和Python的最大不同就是Java是1门强类型的静态语言,使用变量就要声明数据类型;
既然List、Set、Map这3种容器里面,可以存放任何数据类型的元素,那么当我们获取这些元素的时候,就需要进行大量的向下转型操作;
我们不能把食用盐和白砂糖都放在1个罐子里;
泛型:就是通过给容器贴1个标签,规范容器中的元素的数据类型,使集合中存放元素的数据类型保持一致,从而避免了每次对元素的强转操作;
需要注意的是:我们不能给泛型指定primitive type也就是基础的数据类型;
package 泛型; import java.util.*; public class Test01 { public static void main(String[] args) { //注意:变量声明和实例化的时都需要标记泛型<> List<String> list = new ArrayList<String>(); list.add("高俅"); list.add("药店"); list.add("苏东坡"); list.add("驸马"); list.add("端王"); list.add("宋徽宗"); list.add("高太尉"); // list.add(111); //不可以装int System.out.println(list); //获取数据时,不需要强转操作 String s = list.get(list.size() - 1); System.out.println(s); //泛型Map Map<String, String> map = new HashMap<String, String>(); map.put("高二哥", "高俅"); map.put("抓药的", "高俅"); map.put("书童", "高俅"); map.put("北宋太尉", "高俅"); //通过增强for循环 遍历字典 for (String key : map.keySet()) { System.out.printf("%s--%s\n", key, map.get(key)); } } }
六、Collections工具类
由于List、Set、Map这3个接口,向上都实现了1个Collection接口,我把它们统称为集合数据类型;
针对集合数据类型,JDK还提供了1个Collections工具类,帮助我们更便捷地操作使用集合数据类型。
我们主要使用Collections工具类,对集合进行排序、求极值;
package CollectionTools; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; public class Test01 { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(132); list.add(2019); list.add(8866); System.out.println(list); //求最大和最小值 Integer maxNumber = Collections.max(list); Integer minNumber = Collections.min(list); System.out.println(maxNumber); System.out.println(minNumber); //排序 Collections.sort(list); System.out.println(list); //洗牌 Collections.shuffle(list); System.out.println(list); //1次性在列表中添加多个值 Collections.addAll(list, 1, 2, 3, 3); System.out.println(list); } }
七、练习
package CollectionTools; import java.util.*; public class Practive { public static void main(String[] args) { //练习1 //将如下字符串转换成1个TreeMap String dictString = "k1:1,k2:2,k3:3"; String[] klist = dictString.split(","); Map<String, String> kMap = new TreeMap<String, String>(); for (int i = 0; i < klist.length; i++) { String item = klist[i]; String[] subItem = item.split(":"); kMap.put(subItem[0], subItem[1]); } System.out.println(kMap); //练习2 //将小于66的数字保存至sixMap的key1 //将于于66的数字保存至sixMap的key2 int[] numberArray = {11, 22, 33, 44, 55, 66, 77, 88}; Map<String, List<Integer>> sixMap = new HashMap<String, List<Integer>>(); List belongKey1 = new LinkedList(); List belongKey2 = new LinkedList(); for (int i = 0; i < numberArray.length; i++) { int currentNumber = numberArray[i]; if (numberArray[i] <= 66) { belongKey1.add(currentNumber); sixMap.put("key1", belongKey1); } else { belongKey2.add(currentNumber); sixMap.put("key2", belongKey2); } } System.out.println(sixMap); } }