这几天Java学了点新的知识,打算要用这些知识做一个比较简单的管理系统,实战一下子,代码中的功能简洁,可能不多,但是作为一个练手来了解一个项目是怎么样一点一点思考的还是不错的
一.代码中要实现的功能
正所谓一个管理系统不可缺少的功能就是"增 删 查 改"。该程序添加学生信息进而来实现1.根据学号查找2.根据姓名查找3.根据学号删除4.根据学号修改
二.实现中所用到的技术
这个程序主要是针对hashmap的应用,以及接口的实现而呈现出来的,还有如何利用增改删除来实现功能。
三.原理解析
在实现出这个功能的过程还是有一些知识点遗漏了,比如什么hashmap容器中的get(),key值之类的是什么了,怎么用的,都忘记了,还有一些小的概念都忘记了,那下面我就说一下,或许对于你们会的人来说很简单,再简单不过的了,但是我还是总结一下子吧!或许恰巧有的人也正好这个知识点忘记了。
- [1] .implements和extends的区别
1.extends是继承父类的,只要那个类不是声名为final或者那个类定义为abstract就能继承
2.JAVA中不支持多继承,但可以用接口来实现,这是implements就出现了
3.继承只能继承一个类,但是implements可以实现多个接口,用逗号分隔开就好啦!
例如:class A extends B implements C D
也就是说extends是继承类,implements是实现接口
类和接口是不同的:类里是由程序实现的,而接口无程序实现,只可以预定义方法
- [2] Hashmap中put()过程
的源码是JDK1.8的源码。
JDK1.8中,Hashmap将基本元素由Entry换成了Node,不过查看源码后发现换汤不换药,这里没啥好说的。
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node[] tab; Node p; int n, i;
// 判断数组是否为空,长度是否为0,是则进行扩容数组初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 通过hash算法找到数组下标得到数组元素,为空则新建
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node e; K k;
// 找到数组元素,hash相等同时key相等,则直接覆盖
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 该数组元素在链表长度>8后形成红黑树结构的对象,p为树结构已存在的对象
else if (p instanceof TreeNode)
e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
else {
// 该数组元素hash相等,key不等,同时链表长度<8.进行遍历寻找元素,有就覆盖无则新建
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
// 新建链表中数据元素,尾插法
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
// 链表长度>=8 结构转为 红黑树
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
// 新值覆盖旧值
if (e != null) { // existing mapping for key
V oldValue = e.value;
// onlyIfAbsent默认false
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
// 判断是否需要扩容
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
基本过程如下:
检查数组是否为空,执行resize()扩充;在实例化HashMap时,并不会进行初始化数组)
通过hash值计算数组索引,获取该索引位的首节点。
如果首节点为null(没发生碰撞),则创建新的数组元素,直接添加节点到该索引位(bucket)。
如果首节点不为null(发生碰撞),那么有3种情况
① key和首节点的key相同,覆盖old value(保证key的唯一性);否则执行②或③
② 如果首节点是红黑树节点(TreeNode),将键值对添加到红黑树。
③ 如果首节点是链表,进行遍历寻找元素,有就覆盖无则新建,将键值对添加到链表。添加之后会判断链表长度是否到达TREEIFY_THRESHOLD - 1这个阈值,“尝试”将链表转换成红黑树。
最后判断当前元素个数是否大于threshold,扩充数组。
- [3] .Hashmap中get()过程
的源码是JDK1.8的源码。
public V get(Object key) {
Node e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node getNode(int hash, Object key) {
Node[] tab; Node first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
// 永远检查第一个node
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode) // 树查找
return ((TreeNode)first).getTreeNode(hash, key);
do {
if (e.hash == hash && // 遍历链表
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
在Hashmap1.8中,无论是存元素还是取元素,都是优先判断bucket上第一个元素是否匹配,而在1.7中则是直接遍历查找。
基本过程如下:
根据key计算hash;
检查数组是否为空,为空返回null;
根据hash计算bucket位置,如果bucket第一个元素是目标元素,直接返回。否则执行4;
如果bucket上元素大于1并且是树结构,则执行树查找。否则执行5;
如果是链表结构,则遍历寻找目标
上面说的几点是我通过这个简单的小项目进而学习到的知识,上网上查询资料,看源码,并且也看了一些大佬们写的博客,也学习了不少的知识,下面是这个项目的源代码
源代码:
1.student.java
package com.bjsxt.stusys;
/**
* 学生属性:学号,名字,年龄,性别。
* @author
*/
public class Student{
private int sid;
private String name;
private int age;
private Gender gender;
public Student(){
}
public Student(int sid,String name,int age,Gender gender) {
this.sid=sid;
this.name=name;
this.age=age;
this.gender=gender;
}
/**
* 在java中由于类被封装了,所以想要进行访问话,只需要通过外部进行
* 通过set()进行设立一个值,get()获得属性的值
*/
public int getsid() {
return sid;
}
public void setsid(int sid) {
this.sid=sid;
}
public String getname() {
return name;
}
public void setname(String name) {
this.name=name;
}
public int getage() {
return age;
}
public void setage(int age) {
this.age=age;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public String toString() {
return "学生信息{" +
"学号" + sid +
", 名字 = ' " + name + '\'' +
", 年龄= " + age +
", 性别 = " + gender +
'}';
}
}
enum Gender{
男 ,女
}
studentInterface.java
package com.bjsxt.stusys;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**遍历所有学生信息
* 添加学生信息
* 根据学号查找学生
* @author
* 根据名字查找学生
*
*/
public interface StudentInterface {
/**
* 遍历所有学生信息
*/
void showAll();
/**
* 添加学生信息,判断是否添加成功
* @return 加成功,返回true 否则返回false
*/
boolean addStudent();
/**
* 根据学号查找学生
* @param sid
* @return 被找到的学生对象,如果不存在,返回null
*/
Student findStuBySid(int sid);
/**
* 根据名字查找学生
* @param name
* @return 返回所有该名字为name的学生的列表,如果不成功,返回Null
*/
List findStudentByName(String name);
/**
* 根据学号删除学生
* @param sid
* @return 如果删除成功,返回true,否则返回false
*/
boolean removeStuBySid(int sid);
/**
* 根据学号修改学生
* @param sid
* @return 如果修改成功,返回true,否则返回false
*/
boolean modifyStuBySid(int sid);
}
3.studentSystem.java
package com. bjsxt.stusys;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class StudentSystem implements StudentInterface {
//使用HashMap保存所有的学生信息,容器中的Entry的key是学号。value是学号对应的学生对象
private Map students = new HashMap<>();
private Scanner scanner = new Scanner(System.in);
/**
* 欢迎界面
*/
public void welcome() {
System.out.println("*************************欢迎来到我的学生管理系统**************************");
System.out.println("系统初始化成功........");
}
public void exit() {
System.out.println("*************************谢谢使用我的的学生管理系统**************************");
}
/**
* 显示系统菜单
*/
public void showMenu() {
System.out.println("\n操作菜单内容");
System.out.println("1--所有学生信息");
System.out.println("2--添加学生信息");
System.out.println("3--根据学号查找");
System.out.println("4--根据姓名查找");
System.out.println("5--根据学号删除");
System.out.println("6--根据学号修改");
System.out.println("7--退出系统");
}
@Override
public void showAll() {
//得到所有的学生信息
Set sids = students.keySet();//返回包含在映射中得值
Iterator iterator = sids.iterator();//返回该集合中元素的迭代
while(iterator.hasNext()) {//如果是真,则继续返回元素,而不是抛出异常
Integer sid = iterator.next();//把下一个迭代赋给学号
Student student = students.get(sid);//根据学号获得对象,返回关联值 (Student) 的键
System.out.println(student);
}
}
@Override
/**
* 添加学生信息
*/
public boolean addStudent() {//因为接下来的几次都要使用,所以给他封装个方法
//System.out.println("请输入学生的学号,要求是整数:");
//int sid = scanner.nextInt();
int sid = MyUtil.getInputNumber("请输入学生的学号,要求是整数:", scanner);
//System.out.println("请输入学生的学号,要求是整数:");
String name = MyUtil.getInputString("请输入学生的姓名:", scanner);
int age = MyUtil.getInputNumber("请输入学生的年龄:", scanner);
Gender gender = MyUtil.getInputString("请输入学生的性别 男 or 女:", scanner).equals("男")?Gender.男 : Gender.女;
Student s = new Student(sid,name,age,gender);
/**
* 返回与键关联的前一个值,如果没有键的映射,则为空
*/
students.put(sid,s);
System.out.println("添加学生成功");
return true;
}
@Override
public Student findStuBySid(int sid) {
Student student = students.get(sid);
if(student !=null) {
System.out.println(student);
}
else
System.out.println("该学生不存在滴");
return student;
}
/**
* 这个只是为了后面测试的时候可以方便些
* @return
*/
public Student findStuBySid() {
int sid = MyUtil.getInputNumber("请输入要查找的学生的学号", scanner);
return findStuBySid(sid);
}
@Override
public List findStudentByName(String name) {
ListList = new ArrayList<>();
//遍历所有的学生,然后和name逐个比较
Collectionstus =students.values();//返回此映射中的集合视图
Iteratoriterator = stus.iterator();//此集合中元素的迭代器
while(iterator.hasNext()) {
Student student = iterator.next();
if(student.getname().equals(name)) {
List.add(student);
}
}
return List.size()==0 ? null : List;
}
public void findStudentByName(){
String name = MyUtil.getInputString("请输入要查找学生的姓名", scanner);
Liststus = findStudentByName(name);
if(stus==null) {
System.out.println("该姓名的学生不存在");
}
else
{
//打印所有学生的信息
System.out.println("查找到的学生的信息如下 :");
for(int i=0;i
4.MyUtil.java
package com.bjsxt.stusys;
import java.util.Scanner;
/**
* 工具类(写两个方法)
* @author
*/
public class MyUtil {
private MyUtil() {}
/**
* 得到指定区间的随机数
* @param min 包含
* @param max 不包含
* @return
*/
public static int getRandomNumber(int min,int max) {
return(int)(Math.random()*(max-min)+min);
}
public static int getInputNumber(String msg,Scanner scanner) {
System.out.println(msg);
return scanner.nextInt();
}
/**
* 给用和提供信息的同时,请输入一个字符串
* @param msg
* @param scanner
* @return
*/
public static String getInputString(String msg,Scanner scanner) {
System.out.println(msg);
return scanner.next();
}
}
5.TestStudentSystem.java
package com.bjsxt.stusys;
import java.util.Scanner;
/**
* 学生属性:学号,名字,年龄,性别
* @author
* 实现功能:
*遍历所有学生信息
*/
public class TestStudentSystem {
public static void main(String[] args) {
StudentSystem system = new StudentSystem();
//显示欢迎信息
system.welcome();
Scanner scanner = new Scanner(System.in);
while(true) {
system.showMenu();
int input = MyUtil.getInputNumber("请选择您的操作", scanner);
switch(input) {
case 1:
system.showAll();
break;
case 2:
system.addStudent();
break;
case 3 :
system.findStuBySid();
break;
case 4:
system.findStudentByName();
case 5 :
system.removeStuBySid();
break;
case 6:
system.modifyStuBySid();
break;
case 7:
system.exit();
}
}
}
}
运行结果:
*************************欢迎来到肖夕梦的学生管理系统**************************
系统初始化成功........
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
2
请输入学生的学号,要求是整数:
1001
请输入学生的姓名:
小红
请输入学生的年龄:
14
请输入学生的性别 男 or 女:
女
添加学生成功
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
2
请输入学生的学号,要求是整数:
1002
请输入学生的姓名:
小刚
请输入学生的年龄:
15
请输入学生的性别 男 or 女:
男
添加学生成功
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
2
请输入学生的学号,要求是整数:
1005
请输入学生的姓名:
小紫
请输入学生的年龄:
16
请输入学生的性别 男 or 女:
女
添加学生成功
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
1
学生信息{学号1001, 名字 = ' 小红', 年龄= 14, 性别 = 女}
学生信息{学号1002, 名字 = ' 小刚', 年龄= 15, 性别 = 男}
学生信息{学号1005, 名字 = ' 小紫', 年龄= 16, 性别 = 女}
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
3
请输入要查找的学生的学号
1005
学生信息{学号1005, 名字 = ' 小紫', 年龄= 16, 性别 = 女}
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
6
请输入要修该学生的学号
1001
请输入新的学生的学号,要求是整数:
1009
请输入新的学生的姓名:
小红
请输入新的学生的年龄:
12
请输入新的学生的性别:
女
修改学生信息成功 !
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
5
请输入要删除学生的学号
1001
删除学生成功 !
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
1
学生信息{学号1002, 名字 = ' 小刚', 年龄= 15, 性别 = 男}
学生信息{学号1005, 名字 = ' 小紫', 年龄= 16, 性别 = 女}
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
4
请输入要查找学生的姓名
小紫
查找到的学生的信息如下 :
学生信息{学号1005, 名字 = ' 小紫', 年龄= 16, 性别 = 女}
请输入要删除学生的学号
1001
删除学生成功 !
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
1
学生信息{学号1002, 名字 = ' 小刚', 年龄= 15, 性别 = 男}
学生信息{学号1005, 名字 = ' 小紫', 年龄= 16, 性别 = 女}
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
7
*************************谢谢使用肖夕梦的学生管理系统**************************
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
4
请输入要查找学生的姓名
小紫
查找到的学生的信息如下 :
学生信息{学号1005, 名字 = ' 小紫', 年龄= 16, 性别 = 女}
请输入要删除学生的学号
1005
删除学生成功 !
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作
1
学生信息{学号1002, 名字 = ' 小刚', 年龄= 15, 性别 = 男}
操作菜单内容
1--所有学生信息
2--添加学生信息
3--根据学号查找
4--根据姓名查找
5--根据学号删除
6--根据学号修改
7--退出系统
请选择您的操作