🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 概念 **集合是一个容器** 之前学习过数组,也是一个容器 数组特点: ①只能存放相同类型的数据 ②固定长度 ③引用数据类型和基本数据类型都能存储 **集合也能存放一组数据 ①专门存放引用数据类型 ②元素类型可以任意 ③长度不固定(动态扩容)** *** ### 简介 Java当中,集合由两大接口所代表 #### 1.Collection接口(线性集合) 1.1 **List接口**--有序有重复 **有序有重复:元素存入集合中的顺序,与元素在集合中真正的位置是一致的;相同的对象可以多次存入集合**】 1.2 **Set接口**--无序无重复 **无序无重复:元素存入集合中的顺序,与元素在集合中真正的位置是不一定一致的;相同的对象可以只保留一个** *** **面试题:List与Set的区别** List接口--有序有重复,Set接口--无序无重复 *** **List接口实现类** ①**ArrayList**--内部基于数组实现 其实就是创建了一个长度是10的Object类型数组,当元素个数超过10个时,自动扩容到原来长度的1.5倍;内部基于数组实现--所以拥有数组的一些特点:**随机查询速度快**(数组是一个静态线性表,逻辑上和物理上地址都是连续的,通过首地址可以获取到所有数据,通过下标可以获取元素),**插入删除速度慢**(因为地址连续,需要移动元素并更新下标) ②**LinkedList**--内部基于链表实现 链表是一种动态线性表(逻辑上连续,物理上不连续),链表包含两个部分:①元素;②指向下一个元素的指针;特点:**随机查询速度慢**(无论查找第几个元素,必须从第一个元素起始),**插入删除速度快**(因为不涉及元素移动) *** **面试题:ArrayList,LinkedList,Vector的区别** ArrayList随机查询速度快,插入删除速度慢 LinkedList随机查询速度慢,插入删除速度快 Vector与ArrayList的区别是线程安全,而ArrayList线程不安全,效率更高 *** 练习代码 ~~~ public class ArrayListDemo1 { public static void main(String[] args) { // Object ob[] = {1,false,"hello"}; // 1.能存入任意类型对象 // 2.长度可变 List list = new ArrayList(); ArrayListDemo1 ad = new ArrayListDemo1(); // 1.添加元素add list.add(1); list.add(false); list.add("hello"); list.add(ad); list.add(9.9); list.add(ad); // add也可以做插入操作 list.add(1, "123"); System.out.println(list); // 2.集合长度 System.out.println(list.size()); // 3.获取--靠get(下标) System.out.println(list.get(1)); // 4.1普通遍历 // for(int i = 0;i < list.size();i++) { // System.out.println("^^"+list.get(i)); // } // // 4.2增强for循环遍历 // for(Object o:list) { // System.out.println("^^^^"+o); // } // 5.indexOf返回元素索引值,不存在返回-1 // System.out.println(list.indexOf("hello")); // 6.remove // list.remove("1"); // 7.set替换 // list.set(0, 123); // System.out.println(list); } } ~~~ ~~~ public class LinkedListDemo1 { public static void main(String[] args) { LinkedList list = new LinkedList(); list.add("hello"); // list.add(1); // list.add(0, 123); // System.out.println(list); // System.out.println(list.isEmpty()); // // if(list != null && !list.isEmpty()) { // System.out.println(123); // } // // System.out.println(list.get(2)); list.addFirst(123); System.out.println(list); } } ~~~ *** **Set接口实现类** ①**HashSet** ~~~ public class HashSetDemo1 { public static void main(String[] args) { Set set = new HashSet(); HashSetDemo1 hs = new HashSetDemo1(); set.add("hello"); set.add(123); set.add(false); set.add(hs); set.add(hs); // Set没有get方法,也没有下标 // System.out.println(set); // // 遍历 // for(Object o:set) { // System.out.println(o); // } System.out.println(set.size()); System.out.println(set.isEmpty()); set.remove(123); System.out.println(set); // 1.set.contains("hello1") 集合中包含元素返回true,否则返回false System.out.println(set.contains("hello1")); } } ~~~ ②**TreeSet** #### 2.Map接口(非线性集合) Map是以键(key)值(value)对的形式存储元素,key的功能类似于地址,key不允许重复,否则会覆盖value,value随意,null作为键值都是可以的 ①HashMap ②TreeMap ③HashTable *** **面试题:HashMap与HashTable的区别** Hashtable是线程安全的,而HashMap是线程序不安全的。 HashMap允许将null作为一个元素的key或者value,而Hashtable不允许。 *** ### 集合的遍历 ~~~ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class BianLiDemo { public static void main(String[] args) { // 1.集合的遍历--通用--迭代器遍历 List list = new ArrayList(); list.add(4); list.add("hello"); Set<Comparable> set = new HashSet(); set.add("123"); set.add(false); // 1.迭代器遍历List和Set // Iterator iter = set.iterator(); // while(iter.hasNext()) { // Object o = iter.next(); // System.out.println(o); // } // 2.for循环遍历List和Set // for(Object o:set) { // System.out.println(o); // } Map map = new HashMap(); map.put(1, "A"); map.put(null, "Z"); // map.keySet()返回key的Set集合 // Set set1 = map.keySet(); // 1.迭代器遍历Map // Iterator iter = set1.iterator(); // while(iter.hasNext()) { // Object key = iter.next(); // System.out.println(map.get(key)); // } // 2.for循环遍历Map // for(Object key:set1) { // System.out.println(key+" "+map.get(key)); // } // 3.利用Entry遍历Map--最常用的 // 返回entry集合 // Set set1 = map.entrySet(); // for(Object o:set1) { // Entry entry = (Entry)o; // System.out.println(entry.getKey()+" "+entry.getValue()); // } // for(Object o:map.entrySet()) { // Entry entry = (Entry)o; // System.out.println(entry.getKey()+" "+entry.getValue()); // } } } ~~~ *** ### Collections类 **面试题:Collections与Collection的区别?** Collections类是类似于Arrays类的公用工具类 ,它提供了一些static方法供集合类使用或操作集合类 。 Collection是线性集合的父接口 *** ### 泛型(类型参数化) 控制集合元素类型 ~~~ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class FanXingDemo1 { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("123"); list.add("456"); list.add("789"); list.add("10JQ"); // for(String str:list) { // System.out.println(str); // } Set<Person> set = new HashSet<Person>(); set.add(new Person(12,"zhagnsan1")); set.add(new Person(14,"zhagnsan2")); // set.add(new FanXingDemo1()); Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1, "hello1"); map.put(2, "hello2"); for(Entry<Integer, String> entry:map.entrySet()) { System.out.println(entry.getKey()+" "+entry.getValue()); } } } ~~~ *** ### Map与Collection接口特殊应用 Map当中有List(Set) ~~~ public class ListInMapDemo1 { public static void main(String[] args) { Map<String, List<String>> map = new HashMap<String, List<String>>(); List<String> list1 = new ArrayList<String>(); list1.add("张三1"); list1.add("李四2"); list1.add("王五3"); map.put("JAVA1班", list1); // System.out.println(map.get("JAVA1班")); List<String> list2 = new ArrayList<String>(); list2.add("张三4"); list2.add("李四5"); list2.add("王五6"); map.put("JAVA2班", list2); // System.out.println(map.get("JAVA2班")); List<String> list3 = new ArrayList<String>(); list3.add("张三7"); list3.add("李四8"); list3.add("王五9"); map.put("JAVA3班", list3); // System.out.println(map.get("JAVA3班")); // 遍历 for(Entry<String, List<String>> entry:map.entrySet()) { System.out.println(entry.getKey()); List<String> list = entry.getValue(); for(String value:list) { System.out.print(value+" "); } System.out.println(); } } } ~~~ List当中有Map ~~~ public class MapInListDemo1 { public static void main(String[] args) { // List中存放Map List<Map<Integer,String>> list = new ArrayList<Map<Integer,String>>(); Map<Integer,String> map1 = new HashMap<Integer,String>(); map1.put(1,"hello1"); map1.put(2,"hello2"); Map<Integer,String> map2 = new HashMap<Integer,String>(); map2.put(1,"hello3"); map2.put(2,"hello4"); Map<Integer,String> map3 = new HashMap<Integer,String>(); map3.put(1,"hello5"); map3.put(2,"hello6"); list.add(map1); list.add(map2); list.add(map3); // System.out.println(list); // 遍历 for(Map<Integer,String> map:list) { for(Entry<Integer,String> entry:map.entrySet()) { System.out.println(entry.getKey()+" "+entry.getValue()); } } } } ~~~ *** ### 泛型的其他应用 ~~~ public class Point<E,T> { E x; T y; public static void main(String[] args) { Point<Double,Integer> p = new Point<Double,Integer>(); } } ~~~ *** ### 集合练习题--世界杯 利用Map完成如下功能: 从命令行读入一个字符串,表示一个年份,输出该年的世界杯冠军是哪支球队。如果该年没有举办世界杯,则输出:没有举办世界杯。 历届世界杯冠军 届数 举办年份 举办地点 冠军 第一届 1930年 乌拉圭 乌拉圭 第二届 1934年 意大利 意大利 第三届 1938年 法国 意大利 第四届 1950年 巴西 乌拉圭 第五届 1954年 瑞士 西德 第六届 1958年 瑞典 巴西 第七届 1962年 智利 巴西 第八届 1966年 英格兰 英格兰 第九届 1970年 墨西哥 巴西 第十届 1974年 前西德 西德 第十一届 1978年 阿根廷 阿根廷 第十二届 1982年 西班牙 意大利 第十三届 1986年 墨西哥 阿根廷 第十四届 1990年 意大利 西德 第十五届 1994年 美国 巴西 第十六届 1998年 法国 法国 第十七届 2002年 韩日 巴西 第十八届 2006年 德国 意大利 第十九届 2010年 南非 西班牙 第二十届 2014年 巴西 德国 第二十一届 2018年 俄罗斯 法国 (Map)在原有世界杯Map 的基础上,增加如下功能: 读入一支球队的名字,输出该球队夺冠的年份列表。 例如,读入“巴西”,应当输出 1958 1962 1970 1994 2002 读入“荷兰”,应当输出 没有获得过世界杯 ![](https://box.kancloud.cn/1cba2c96dd7ee24d2f57d48d4594277f_158x216.png) ![](https://box.kancloud.cn/22bfee403498f655313f45648e3ae089_163x128.png) *** ### 集合练习题--奥运会分组 已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数 2008 北京奥运会男足参赛国家: 科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚,日本,美国,中国,新西兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利 提示:分配一个,删除一个 ![](https://box.kancloud.cn/e8d0f4adfca206e029023f320674cf49_201x153.png) ~~~ package com.neuedu.daka; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class Olympic { public static void main(String[] args) { String str = "科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚,日本,美国,中国,新西兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利"; String cStr[] = str.split(","); List<String> country = new ArrayList<>(); for(String s : cStr) { country.add(s); } Map<String, List<String>> map = new HashMap<>(); for(int i = 0;i < 4;i++) { List<String> gc = new ArrayList<>(); for(int j = 0;j < 4;j++) { int random = (int)(Math.random()*country.size()); gc.add(country.get(random)); country.remove(random); } map.put("第"+(i+1)+"组", gc); } for(Entry<String, List<String>> entry:map.entrySet()) { System.out.println(entry.getKey()); for(String con:entry.getValue()) { System.out.println(con); } System.out.println("---------------------"); } } } ~~~ *** ### 集合练习题--员工打卡 Employee.java ~~~ public class Employee { private int empno; private String name; public Employee() { } public Employee(int empno, String name) { super(); this.empno = empno; this.name = name; } public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ~~~ Company.java ~~~ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Company { // 打卡记录名单 private Map<String,List<DaKaInfo>> map = new HashMap<String,List<DaKaInfo>>(); // 员工集合--名单 private List<Employee> list = new ArrayList<Employee>(); public List<Employee> getList(){ return list; } public Map<String,List<DaKaInfo>> getMap(){ return map; } /** * 添加员工 * @param e 员工对象 */ public void addEmployee(Employee e) { // 查询员工工号是否被占用 for(Employee emp:list) { if(emp.getEmpno() == e.getEmpno()) { System.out.println("员工工号已经占用"); return; } } if(list != null) { list.add(e); System.out.println("员工添加成功"); } } /** * 根据empno查找员工 * @param empno 员工工号 * @return 找到的员工对象 */ public Employee findEmployee(int empno) { if(list != null && !list.isEmpty()) { for(Employee emp:list) { if(emp.getEmpno() == empno) { return emp; } } } return null; } /** * 根据empno删除员工 * @param empno 员工工号 */ public void deleteEmployee(int empno) { if(list != null && !list.isEmpty()) { for(Employee emp:list) { if(emp.getEmpno() == empno) { list.remove(emp); System.out.println("员工删除成功..."); return; } } System.out.println("查无此人"); } } /** * 显示所有员工信息 */ public void showInfo() { if(list != null && !list.isEmpty()) { for(Employee emp:list) { System.out.println("员工工号:"+emp.getEmpno()+",员工姓名: "+emp.getName()); } } } } ~~~ DaKaInfo.java ~~~ public class DaKaInfo { private int empno;// 工号 private Date startTime;// 签到时间 private Date endTime;// 签退时间 public DaKaInfo() { } public DaKaInfo(int empno, Date startTime, Date endTime) { super(); this.empno = empno; this.startTime = startTime; this.endTime = endTime; } public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } } ~~~ Main.java ~~~ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map.Entry; import java.util.Scanner; public class Main { public static Company company = new Company(); // 签到 public static void start(int empno) { // 1.判断是否有这个人,调用company的findEmployee Employee e = company.findEmployee(empno); if(e != null) { // 2.判断是否打过卡 // 2.1判断是不是第一个打卡的人--查看Map中是否有当天key值 Date date = new Date(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss"); String strDate = sdf1.format(date); // 判断map中是否有strDate,从而判断出是否是以一个打卡的人 if(company.getMap().containsKey(strDate)) { // 不是第一个打卡 List<DaKaInfo> list = company.getMap().get(strDate); // 查看是否打过卡 if(list != null && !list.isEmpty()) { for(DaKaInfo dk1:list) { if(dk1.getEmpno() == empno) { System.out.println("您今天 "+sdf2.format(dk1.getStartTime())+" 已经打过卡"); return; } } } // 没有打过卡直接存打卡信息 DaKaInfo dk = new DaKaInfo(); dk.setEmpno(empno); dk.setStartTime(date); list.add(dk); }else { // 是第一个打卡 List<DaKaInfo> list = new ArrayList<DaKaInfo>(); // 存打卡信息 DaKaInfo dk = new DaKaInfo(); dk.setEmpno(empno); dk.setStartTime(date); // 将打卡记录存入list list.add(dk); // 将key值和list存入map company.getMap().put(strDate, list); } System.out.println(empno+"号员工打卡成功"); }else { System.out.println("查无此人"); } } // 签退 public static void end(int empno) { Employee e = company.findEmployee(empno); if(e != null) { Date date = new Date(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); String strDate = sdf1.format(date); if(company.getMap().containsKey(strDate)) { List<DaKaInfo> list = company.getMap().get(strDate); if(list != null && !list.isEmpty()) { for(DaKaInfo dk1:list) { if(dk1.getEmpno() == empno) { dk1.setEndTime(date); System.out.println("签退成功"); return; } } System.out.println(empno+"工号员工今天还没有签到"); } }else { System.out.println(strDate+"暂无打卡记录"); } }else { System.out.println("查无此人"); } } // 查询 public static void showDaKaInfo() { System.out.println("打卡信息如下:"); SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss"); for(Entry<String, List<DaKaInfo>> entry:company.getMap().entrySet()) { System.out.println(entry.getKey()+"打卡记录如下:"); for(DaKaInfo dk:entry.getValue()) { System.out.println("工号:"+dk.getEmpno()+",签到时间:"+sdf2.format(dk.getStartTime())+",签退" + "时间:"+(dk.getEndTime()==null?"暂未签退":sdf2.format(dk.getEndTime()))); } } } public static void main(String[] args) { company.addEmployee(new Employee(1001, "小明")); company.addEmployee(new Employee(1002, "小红")); company.addEmployee(new Employee(1003, "小虎")); company.addEmployee(new Employee(1004, "小兰")); company.addEmployee(new Employee(1005, "小刚")); while(true) { System.out.println("欢迎使用Java5班打卡系统"); System.out.println("=================="); System.out.println("员工打卡-----------1"); System.out.println("员工签退-----------2"); System.out.println("查询所有打卡记录-----3"); System.out.println("Exit-------------4"); Scanner scan = new Scanner(System.in); try { int option = scan.nextInt(); if(option < 1 || option > 4) { System.out.println("无效选项"); continue; }else { switch(option) { case 1: // 打卡 System.out.println("请输入工号:"); int empno1 = scan.nextInt(); start(empno1); break; case 2: // 签退 System.out.println("请输入工号:"); int empno2 = scan.nextInt(); end(empno2); break; case 3: // 查询 showDaKaInfo(); break; case 4: System.out.println("谢谢,再见!"); return; } } } catch (Exception e) { System.out.println("请输入数字"); } } } } ~~~