学习笔记——Java 集合
一、学习重点
二、学习内容
员工管理系统
package com.jsoft.test; import java.math.BigDecimal; import java.util.List; import java.util.Scanner; /** * 用list集合和面向对象写一个员工管理 * 包括登录!!! */ public class Demo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("-----欢迎使用本系统-----"); GUI.userMenu(sc); // ArrayList内部结构数组 // 内部的数组的长度 // List<Employee> list = new ArrayList<>(16); // Employee e = new Employee(1001, "张三", new BigDecimal("10000")); // list.add(e); // // list.contains(); // list.add(11); // null异常 // System.out.println(list.get(0).toString()); // EmployeeService employeeService = new EmployeeService(); // List<Employee> emps = employeeService.getEmps(); // contains判断的如果是基本数据类型 比值 // 如果判断的是引用数据类型 地址 // System.out.println(emps.contains(e)); } }
package com.jsoft.test; import java.math.BigDecimal; public class Employee { private Integer empId; private String name; private BigDecimal salary; // private Dept dept; public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public Integer getEmpId() { return empId; } public void setEmpId(Integer empId) { this.empId = empId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getSalary() { return salary; } public void setSalary(BigDecimal salary) { this.salary = salary; } public Employee() { } public Employee(Integer empId, String name, BigDecimal salary,Dept dept) { this.empId = empId; this.name = name; this.salary = salary; this.dept = dept; } @Override public String toString() { return "Employee{" + "empId=" + empId + ", name='" + name + '\'' + ", salary=" + salary + ", dept=" + dept + '}'; } }
package com.jsoft.test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; /** * 新增的需求: * 1.新增的用户密码的修改*** * 2.新增一个部门选项,员工要对应有部门信息*** * * * 3.思想:能不能优化一下?界面操作,能不能想一些办法提取成方法? * 4.选做:部门管理 * 5.选做:根据薪水排序 * * 员工和部门之间是有关联关系? * * 在给员工指定部门的时候,如果部门不存在。 * */ public class EmployeeService { private List<Employee> emps = new ArrayList<>(16); { emps.add(new Employee(1001, "神山飞羽真", new BigDecimal("10000"),new Dept(1001,"开发部"))); emps.add(new Employee(1002, "宝生永梦", new BigDecimal("5000"),new Dept(1001,"开发部"))); emps.add(new Employee(1003, "天道总司", new BigDecimal("3000"),new Dept(1002,"测试部"))); emps.add(new Employee(1004, "帕拉德", new BigDecimal("1000"),new Dept(1003,"运维部"))); } public void setEmps(List<Employee> emps) { this.emps = emps; } // 新增员工,新增成功后,会展示新增的员工信息。 // 用集合来保存员工 public Employee addEmployee(Employee employee) { // 1.拿到最后一个员工 Employee lastEmp = emps.get(emps.size() - 1); // 2.拿到最后一个员工的工号 Integer lastId = lastEmp.getEmpId(); // 3.工号自增 lastId++; // 4.设置要保存的员工的工号 employee.setEmpId(lastId); // 5.把员工添加到员工列表 emps.add(employee); return employee; } // 查询所有 public List<Employee> getEmps() { return emps; } // 根据工号查询 public Employee getEmpById(Integer id){ for (int i = 0; i < emps.size(); i++) { if(id.equals(emps.get(i).getEmpId())){ return emps.get(i); } } return null; } // 修改 public Employee updateEmpById(Integer id,Employee employee){ // 先查询员工是否存在 int index = -1; for (int i = 0; i < emps.size(); i++) { if(id.equals(emps.get(i).getEmpId())){ index = i; break; } } if(index != -1){ emps.set(index,employee); return employee; } return null; } // 根据id删除 public Employee deleteEmpById(Integer id){ Employee empById = getEmpById(id); return emps.remove(empById) ? empById : null; } // 根据姓名删除 public List<Employee> deleteEmpByName(String name) { // 根据姓名查询,有可能查到的是多个人 // 这个集合要存的信息就是根据姓名找到的员工们 List<Employee> target = new ArrayList<>(16); for (int i = 0; i < emps.size(); i++) { if(name.equals(emps.get(i).getName())){ target.add(emps.get(i)); } } if(target.size() != 0){ emps.removeAll(target); return target; } return null; } }
package com.jsoft.test; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public User(String username, String password) { this.username = username; this.password = password; } }
package com.jsoft.test; import java.util.ArrayList; import java.util.List; public class UserService { private List<User> users = new ArrayList<>(); { users.add(new User("admin","123456")); } // 判断用户名和密码对不对 public boolean login(User user) { for (int i = 0; i < users.size(); i++) { if(user.getUsername().equals(users.get(i).getUsername()) && user.getPassword().equals(users.get(i).getPassword())){ return true; } } return false; } // 判断用户名是否存在 public boolean register(User user){ for (int i = 0; i < users.size(); i++) { if(user.getUsername().equals(users.get(i).getUsername())){ return true; } } users.add(user); return false; } /* 1.用户名是否存在 2.验证原始密码对不对 3.修改密码 */ public boolean updatePassword(User user,String newPassword){ int index = -1; User target = null; for (int i = 0; i < users.size(); i++) { if(user.getUsername().equals(users.get(i).getUsername()) && user.getPassword().equals(users.get(i).getPassword())){ index = i; target = users.get(i); break; } } // if(validateUsername(user.getUsername())){ // // } if(index != -1) { target.setPassword(newPassword); users.set(index,target); return true; } // 如果是return false,原始用户名或密码错误 return false; } // 判断用户名是否存在 public boolean validateUsername(String username){ for (int i = 0; i < users.size(); i++) { if(username.equals(users.get(i).getUsername())){ return true; } } return false; } }
package com.jsoft.test; public class Dept { private Integer id; private String name; public Dept() { } public Dept(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dept{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
package com.jsoft.test; import java.util.ArrayList; import java.util.List; public class DeptService { private List<Dept> depts = new ArrayList<>(); { depts.add(new Dept(1001,"开发部")); depts.add(new Dept(1002,"测试部")); depts.add(new Dept(1003,"运维部")); } public List<Dept> getDepts() { return depts; } public void setDepts(List<Dept> depts) { this.depts = depts; } }
package com.jsoft.test; public enum Message { ; private String info; Message(String info){ this.info = info; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } }
package com.jsoft.test; import java.math.BigDecimal; import java.util.List; import java.util.Objects; import java.util.Scanner; public class GUI { private static EmployeeService employeeService = new EmployeeService(); private static UserService userService = new UserService(); private static DeptService deptService = new DeptService(); public static void userMenu(Scanner sc) { main:while(true){ System.out.println("请选择操作:1.登录\t2.注册\t3.修改个人密码\t4.退出系统"); String flag = sc.next(); switch (flag){ case "1": while(true){ System.out.println("请输入用户名:"); String username = sc.next(); System.out.println("请输入密码:"); String password = sc.next(); // 比对 boolean login = userService.login(new User(username, password)); if(login){ System.out.println("登录成功!"); // 加载员工管理模块 employeeMenu(sc); continue main; }else { System.out.println("用户名或密码错误..."); continue; } } case "2": ru:while(true){ System.out.println("请输入用户名:"); String username1 = sc.next(); if(userService.validateUsername(username1)){ System.out.println("用户名已存在,请重新输入..."); continue ru; }else { System.out.println("请输入密码:"); String password1 = sc.next(); userService.register(new User(username1,password1)); System.out.println("注册成功!请登录..."); continue main; } } case "3": while(true){ System.out.println("请输入用户名:"); String username2 = sc.next(); System.out.println("请输入原始密码:"); String password2 = sc.next(); System.out.println("请输入新始密码:"); String newPassword = sc.next(); boolean b = userService.updatePassword(new User(username2, password2), newPassword); if(b) { System.out.println("修改密码成功,请登录..."); continue main; } System.out.println("原始用户名或密码错误,请重新输入..."); } case "4": System.out.println("系统退出中..."); break main; } } } private static void employeeMenu(Scanner sc) { main:while(true){ System.out.println("欢迎来到员工管理:1.新增员工\t2.查询员工\t3.修改员工\t4.删除员工\t5.返回上一层"); String flag = sc.next(); switch (flag) { case "1": System.out.println("请输入员工姓名:"); String name = sc.next(); System.out.println("请输入员工的薪水:"); String salaryStr = sc.next(); BigDecimal salary = new BigDecimal(salaryStr); System.out.print("请选择部门:\t"); List<Dept> depts = deptService.getDepts(); for (int i = 0; i < depts.size(); i++) { String deptName = depts.get(i).getName(); System.out.print((i+1) + "、" + deptName + "\t"); } System.out.println(); String deptFlag = sc.next(); Employee employee = new Employee(); employee.setName(name); employee.setSalary(salary); for (int i = 0; i < depts.size(); i++) { // 如果i=0 // deptFlag = 1 if(deptFlag.equals(String.valueOf(i+1))) { employee.setDept(depts.get(i)); } } Employee employee1 = employeeService.addEmployee(employee); System.out.println("新增员工成功,员工的信息为:" + employee1); continue main; case "2": System.out.println("请选择:1、查询所有\t2、根据工号查询"); String s = sc.next(); if(s.equals("1")){ System.out.println(employeeService.getEmps()); }else if(s.equals("2")){ System.out.println("请输入工号:"); String empId = sc.next(); Employee empById = employeeService.getEmpById(Integer.parseInt(empId)); if (Objects.isNull(empById)) { System.out.println("查无此人..."); }else { System.out.println(empById); } } continue main; case "3": System.out.println("请输入要修改的员工的工号:"); String empId = sc.next(); System.out.println("请输入员工的姓名:"); String name3 = sc.next(); System.out.println("请输入员工的薪水:"); String salaryStr3 = sc.next(); BigDecimal salary3 = new BigDecimal(salaryStr3); System.out.print("请选择部门:\t"); List<Dept> depts1 = deptService.getDepts(); for (int i = 0; i < depts1.size(); i++) { String deptName = depts1.get(i).getName(); System.out.print((i+1) + "、" + deptName + "\t"); } System.out.println(); String deptFlag1 = sc.next(); Employee employee3 = new Employee(); employee3.setEmpId(Integer.parseInt(empId)); employee3.setName(name3); employee3.setSalary(salary3); for (int i = 0; i < depts1.size(); i++) { // 如果i=0 // deptFlag = 1 if(deptFlag1.equals(String.valueOf(i+1))) { employee3.setDept(depts1.get(i)); } } Employee result = employeeService.updateEmpById(Integer.parseInt(empId), employee3); if(Objects.isNull(result)){ System.out.println("查无此人,修改失败..."); continue main; } System.out.println("修改成功!修改后的信息为:" + result); continue main; case "4": System.out.println("请选择:1.根据工号删除\t2.根据姓名删除"); String flag4 = sc.next(); switch (flag4) { case "1": System.out.println("请输入工号:"); String empId4 = sc.next(); Employee employee2 = employeeService.deleteEmpById(Integer.parseInt(empId4)); if(Objects.isNull(employee2)){ System.out.println("删除失败,查无此人..."); }else { System.out.println("删除成功..."); } continue main; case "2": System.out.println("请输入姓名:"); String name4 = sc.next(); List<Employee> employees = employeeService.deleteEmpByName(name4); // 如果集合为空,查无此人 // 如果集合不为空,删除的人的信息 if(employees.size() == 0){ System.out.println("查无此人..."); }else { System.out.println("删除成功,删除的人的信息如下:"); System.out.println(employees); } continue main; } case "5": return; } } } }
三、笔记内容
List:数组是有顺序的(添加的先后顺序),数据是可以重复
ArrayList:内部结构是数组。比较适合做高频率的查找,遍历(线程异步,线程不安全,效率高)
LinkedList:双向链表。比较适合做高频率的新增和删除。
Vector:和ArrayList几乎一模一样(线程同步,线程安全)
面试题:
1、Collection和Map接口的区别
2、ArrayList和LinkedList的区别
3、ArrayList和Vector的区别
public static void main(String[] args) { // List<String> list = new LinkedList<>(); LinkedList<String> list = new LinkedList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); //创建对象的时候用的是多态 //父类对象--->子类引用 //我们创建的对象只能够调用父类和子类中都有的方法 list.addFirst("e"); list.addLast("f"); //根据下表索引获取指定位置的元素(模拟场景) System.out.println(list.get(2)); System.out.println(list); }
Collection接口:
List:有顺序,元素可以重复,顺序指的是添加的先后顺序
Set:没有顺序,元素不可以重复,顺序指的是添加的先后顺序
Set其实是有顺序的,内部有个专门排序的算法
1、所谓的无序不等于随机
2、所谓的无序指的是没有按照添加的先后顺序,其实内部是做了排序的
面试题:
1、List和Set区别
2、HashSet和LinkedHashSet的区别和联系
public static void main(String[] args) { Set<Integer> set = new HashSet<>(); set.add(Integer.valueOf(200)); set.add(1); set.add(2); set.add(4); set.add(56); set.add(33); set.add(Integer.valueOf(200)); System.out.println(set); }
import java.util.HashSet; import java.util.Set; /** * Set集合如何确保数据的不重复? * 保证数据类型的类要重写hashCode和equals方法。 */ public class Ch03 { public static void main(String[] args) { Set<Person> set = new HashSet<>(); set.add(new Person("张三",1001)); set.add(new Person("张三",1001)); set.add(new Person("张三",1001)); set.add(new Person("张三",1001)); // 引用数据类型 // set集合所谓的不能重复,默认情况下比较地址 System.out.println(set); } }
TreeSet
排序规则:
要排序的对象的类必须实现Comparable接口
public static void main(String[] args) { /*Set<Integer> tree = new TreeSet<>(); tree.add(-12); tree.add(-10); tree.add(12); tree.add(-123);*/ Set<Person> tree = new TreeSet<>(); tree.add(new Person("张岳",1001)); tree.add(new Person("李四",1010)); tree.add(new Person("费四",1003)); System.out.println(tree); }
LinkedHashSet:在添加数据的同时维护数据的添加顺序
效率要比HashSet略低一些。
public static void main(String[] args) { LinkedHashSet<String> set = new LinkedHashSet<>(); set.add("1"); set.add("a"); set.add("哈哈哈哈"); set.add("%"); System.out.println(set); }
比较接口:
Comparable接口:自然排序,排序规则是固定
Comparator接口:临时排序
public static void main(String[] args) { List<Person> list = new ArrayList<>(16); list.add(new Person("张岳",1100)); list.add(new Person("李四",1010)); list.add(new Person("刘海柱",1020)); // list.sort(new Comparator<Person>() { // @Override // public int compare(Person o1, Person o2) { // return 0; // } // }); list.sort((o1,o2) -> { if(o1.getId() < o2.getId()){ return -1; } if(o1.getId().equals(o2.getId())){ return 0; } return 1; }); System.out.println(list); }
Map接口:
1、存储对值K-V key-value
2、key不能重复,Value可以重复
3、没有顺序(添加的先后顺序)
HashMap内部存储结构:
JDK1.7之前:链表 + 二叉树
JDK1.7及之后:链表 + 数组 + 红黑树
HashMap基本上面试90%问原理!!!
public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("1001","天道总司"); map.put("1002","宝生永梦"); map.put("1003","帕拉德"); map.put("1004","飞羽真"); System.out.println(map); System.out.println(map.get("1003")); System.out.println(map.values()); System.out.println(map.keySet()); }
Hashtable和HashMap几乎一模一样
面试题:
Hashtable和HashMap的区别
1、HashMap是线程异步,线程不安全。Hashtable是线程同步,线程安全
2、HashMap的key是可以为null的。Hashtable是不可以为null的
public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put(null,null); System.out.println(map); Hashtable<String, String> table = new Hashtable<>(); table.put(null,null); System.out.println(table); }
Properties:属性
Properties是Hashtable的子类,更多的是用来操作属性文件
List集合的遍历
ArrayList
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Ch10 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); //1、for循环 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } //2、foreach语句 for (String s : list) { System.out.println(s); } //3、迭代器 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String s = iterator.next(); iterator.remove(); // System.out.println(s); } System.out.println(list); } }
HashSet
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Ch11 { public static void main(String[] args) { Set<Integer> set = new HashSet<>(); set.add(1); set.add(2); set.add(4); //1、增强for循环 for (Integer integer : set) { System.out.println(integer); } //2、迭代器 Iterator<Integer> iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
HashMap
import java.util.*; public class Ch12 { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("1001","张岳"); map.put("1002","赵红兵"); map.put("1003","小北京"); map.put("1004","李四"); map.put("1005","张浩然"); // 4.迭代器 Set<String> strings = map.keySet(); Iterator<String> iterator = strings.iterator(); while(iterator.hasNext()) { String s = iterator.next(); System.out.println(s + "->" + map.get(s)); } // 3.增强for循环 // Entry是hashmap的一个内部类 // 每一组键值对就是一个Entry对象 // Set<Map.Entry<String, String>> entries = map.entrySet(); // for (Map.Entry<String, String> entry : entries) { // System.out.print(entry.getKey() + "->"); // System.out.println(entry.getValue()); // } // 2.增强for循环 // Set<String> strings = map.keySet(); // Collection<String> values = map.values(); // 1.for循环 // Set<String> strings = map.keySet(); // for (String s : strings) { // System.out.println(s + "->" + map.get(s)); // } } }
迭代中删除元素
public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("tom"); names.add("lucy"); names.add("lucy"); names.add("lucy"); names.add("jerry"); // for (int i = 0; i < names.size(); i++) { // if(Objects.equals(names.get(i),"lucy")){ // names.remove(i); // // 1.回调指针 // i--; // } //// if("lucy".equals(names.get(i))){ //// //// } // } // 2.逆序遍历 // for (int i = names.size() - 1; i >= 0; i--) { // if(Objects.equals(names.get(i),"lucy")){ // names.remove(i); // } // } // 3.使用迭代器(推荐)万无一失 Iterator<String> iterator = names.iterator(); while(iterator.hasNext()) { String s = iterator.next(); if(Objects.equals(s,"lucy")){ iterator.remove(); } } // 4.增强for循环 // for (String s : names) { // if(Objects.equals(s,"lucy")){ // names.remove(names.indexOf(s)); // } // } System.out.println(names); }
其他的集合:
1.LinkedHashMap:在HashMap的基础上维护了一个双向链表。
2.TreeMap:天然支持排序
3.Collections:Collections是一个工具类
面试题:
线程安全问题:
迭代器是依赖于集合而存在,在判断成功以后,集合中新增了元素,
迭代器不知道,所以就报错。
解决:
1.迭代器遍历元素,迭代器删除元素
2.普通for循环遍历,集合删除
public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("tom"); names.add("lucy"); names.add("lucy"); names.add("lucy"); names.add("jerry"); for (String s : names) { if(Objects.equals(s,"lucy")){ // names.remove(s); names.add(s); } }
Person类
public class Person implements Comparable<Person> { private String name; private Integer id; public Person(String name, Integer id) { this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (!name.equals(person.name)) return false; return id.equals(person.id); } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + id.hashCode(); return result; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", id=" + id + '}'; } /* 返回值代表什么? int 代表排序结果 负数-1:比较的两个值调用者小 0:两个值相等 正数1:比较的两个值调用者大 */ @Override public int compareTo(Person p) { if(this.id > p.id){ return -1; } if(this.id.equals(p.id)){ return 0; } return 1; } }
集合总结:
集合需要掌握的:
1.如何创建需要的集合。多态
2.主要用到的是List和Map
3.各种区别?
4.各种集合API的调用
5.两个比较接口
6.各种集合的特点,从接口层面,到实现类层面
7.重点集合的内部结构。ArrayList,HashSet,HashMap
8.各种集合的遍历
9.并发问题
最重要的集合:
ArrayList、HashMap
积压的问题:
1.synchronize原理
2.ReentrantLock原理
3.ArrayList原理
4.LinkedList原理
5.HashMap原理***************
6.HashSet原理
List->Map->Set