這幾天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<K,V>[] tab; Node<K,V> 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<K,V> 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<K,V>)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<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> 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<K,V>)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<Student> 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<Integer,Student> 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<Integer> sids = students.keySet();//返回包含在映射中得值
Iterator<Integer> 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<Student> findStudentByName(String name) {
List<Student>List = new ArrayList<>();
//遍歷所有的學生,然后和name逐個比較
Collection<Student>stus =students.values();//返回此映射中的集合視圖
Iterator<Student>iterator = 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);
List<Student>stus = findStudentByName(name);
if(stus==null) {
System.out.println("該姓名的學生不存在");
}
else
{
//打印所有學生的信息
System.out.println("查找到的學生的信息如下 :");
for(int i=0;i<stus.size();i++) {
System.out.println(stus.get(i));
}
}
}
@Override
public boolean removeStuBySid(int sid) {
Student student = students.remove(sid);
return student == null ? false : true;
}
@SuppressWarnings("unused")
public void removeStuBySid() {
int sid = MyUtil.getInputNumber("請輸入要刪除學生的學號", scanner);
boolean bool = removeStuBySid(sid);
if(true) {
System.out.println("刪除學生成功 !");
}
else
{
System.out.println("該學生不存在 !");
}
}
@Override
public boolean modifyStuBySid(int sid) {
Student student = students.get(sid);
if(student != null) {
sid = MyUtil.getInputNumber("請輸入新的學生的學號,要求是整數:", scanner);
String name = MyUtil.getInputString("請輸入新的學生的姓名:", scanner);
int age = MyUtil.getInputNumber("請輸入新的學生的年齡:", scanner);
Gender gender = MyUtil.getInputString("請輸入新的學生的性別:", scanner).equals("男")?Gender.男 : Gender.女;
student.setage(age);
student.setname(name);
student.setsid(sid);
student.setGender(gender);
}
return student == null ? false : true;
}
public void modifyStuBySid() {
int sid = MyUtil.getInputNumber("請輸入要修該學生的學號", scanner);
boolean bool = modifyStuBySid(sid);
if(bool) {
System.out.println(" 修改學生信息成功 !");
}else {
System.out.println(" 學生不存在 !");
}
}
}
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--退出系統
請選擇您的操作