为模拟向数据库中大量插入学生数据(注:此处应该用PreparedStatement、batchUpdate等批处理提高效率)的情形,通过Java随机来生成学生数据。
一、要生成的学生数据
students表设计如下:
其中前三项是数据库自动生成的,后面的10项需要程序生成。
>>基于实际要求,插入的Student数据中,major和jnshuId不能同时相同。但由于随机数的不确定性,在程序中限制两个Student的major和jnshuId不同时相同复杂而低效。因此,选择在数据库中将major和jnshuId设为联合唯一性索引,然后在插入数据时忽略重复值。
因此,设计RandomStudent类如下:
通过getStudent方法生成学生数据,其中的各种getXxx方法都是随机生成各种数据的静态方法。
public static Student getStudent() {
Student stu = new Student(getName(), getMajor(), getJnshuId());
stu.setQq(getQq());
stu.setEntryTime(getEntryTime());
stu.setSchool(getSchool());
stu.setDailyUrl(getDailyUrl());
stu.setDesire(getDesire());
stu.setJnshuBro(getJnshuBro());
stu.setKnowFrom(getKnowFrom());
return stu;
}
二、Java中的随机
Java中常见的有三种随机方式:
- java.lang.Math.random():返回一个0≤x<1.0的double值。在一次JVM的运行中,只创建一个伪随机数生成器,之后对该方法的所有调用,都是通过该生成器来生成随机数。此方法是同步的,可以在多线程中正确运行,但如果有大量线程需要高速生成随机数,对该生成器的争用会降低效率。
- java.util.Random类:实现更多功能的随机数生成。每创建一个对象就会创建一个伪随机数生成器,只要seed不同,生成的随机数序列就会不同;seed相同时,生成的随机数序列完全相同。该类有两种构造方法:
- Random():用某个seed创建一个随机数生成器。在一次JVM的运行中,创建每个随机数生成器的seed都不同。也就是说,用此方法创建的多个random对象,生成的随机数序列一定不同(除非用setSeed方法改变seed)。在多线程中,可以每个线程中创建一个random对象,这样就避免了对随机数生成器的争用。
- Random(long seed):用给定seed创建随机数生成器。可通过相同seed创建random对象,生成相同的随机数序列。
- java.security.SecureRandom类:提供强加密随机数生成器。
这里不需要用到多线程,也不需要多样化的随机数生成方法,选择Math.random()即可。
注意,用于生成int随机数时,(int) (x*Math.random())生成的随机数范围为0~x-1。
三、随机程序设计
各种获取随机值的函数,从随机类型上可以分为以下几种:
1.不确定的部分是一定范围内的随机数,比如getJnshuId()、getEntryTime()。
将范围的差值乘Math.random(),强转为范围类型后,加上范围最小值,即得范围内的随机数:
//例:获取范围在min到max之间的随机数(int)。
//按照Java惯例,范围含头不含尾。
int random = (int) ((max-min)*Math.random())+min;
2.从几个预设值中随机选取一个,比如getSchool()、getMajor()。
用1中方法获取数组角标范围内的随机数作为角标,获取数组值:
//例:随机选取5个字符中的1个。
char[] array = {'a','b','c','d','e'};
int pos = (int) (5*Math.random());
char random = array[pos];
3.长度随机,每个字符的值也随机,比如getName()、getQq()。
首先用1中方法获取长度的随机值,然后用for循环,以随机长度作为循环结束条件,每次循环中用2中方法获取随机字符,加到字符串中。
//例:随机5-10位长度的字符串,每个字符在字符数组中随机选取。
char[] array = {'a','b','c','d','e','1','2','3','4','5'};
int length = (int) ((11-5)*Math.random())+5;
StringBuilder random = new StringBuilder();
for(int i = 0;i<length;i++) {
int pos = (int) (10*Math.random());
random.append(array[pos]);
}
String str = random.toString();
四、程序编写
整个程序代码如下:
/**
* @FileName:RandomStudent.java
* @description:用于生成随机学生数据的工具类
* @author Cage Yang
* @version 1.1
* Modified Date:2017年8月13日
* Why & What is modified:
* 1.将getName()、getQq()中,未完成的字符串类型改为StringBuilder,否则会产生大量垃圾字符串对象。
*/
package cn.cage.student; import static java.lang.Math.random; import java.sql.Date;
import java.util.Calendar; /**
* @ClassName RandomStudent
* @description
* @author Cage Yang
*/
public class RandomStudent { /**
* @description 随机生成学生数据,由这些数据创建学生对象并返回。
* @return 生成的学生对象
*/
public static Student getStudent() {
Student stu = new Student(getName(), getMajor(), getJnshuId());
stu.setQq(getQq());
stu.setEntryTime(getEntryTime());
stu.setSchool(getSchool());
stu.setDailyUrl(getDailyUrl());
stu.setDesire(getDesire());
stu.setJnshuBro(getJnshuBro());
stu.setKnowFrom(getKnowFrom());
return stu;
} /**
* @description 随机生成学生姓名。有20种姓氏;名字长度可能有1-2位,共有6480中组合。共有129600种可能的姓名组合。
* @return 生成的学生姓名。
*/
public static String getName() {
String[] firstNameArray = { "李", "王", "张", "刘", "陈", "杨", "赵", "黄", "周", "吴", "徐", "孙", "胡", "朱", "高", "欧阳",
"太史", "端木", "上官", "司马" };// 20个姓,其中5个复姓
String[] lastNameArray = { "伟", "勇", "军", "磊", "涛", "斌", "强", "鹏", "杰", "峰", "超", "波", "辉", "刚", "健", "明", "亮",
"俊", "飞", "凯", "浩", "华", "平", "鑫", "毅", "林", "洋", "宇", "敏", "宁", "建", "兵", "旭", "雷", "锋", "彬", "龙", "翔",
"阳", "剑", "静", "敏", "燕", "艳", "丽", "娟", "莉", "芳", "萍", "玲", "娜", "丹", "洁", "红", "颖", "琳", "霞", "婷", "慧",
"莹", "晶", "华", "倩", "英", "佳", "梅", "雪", "蕾", "琴", "璐", "伟", "云", "蓉", "青", "薇", "欣", "琼", "宁", "平",
"媛" };// 80个常用于名字的单字
int firstPos = (int) (20 * random());
StringBuilder name = new StringBuilder(firstNameArray[firstPos]);
int lastLen = (int) (2 * random()) + 1;
/*
* 为了各函数的统一性,此处也用for循环实现 int lastPos1 = (int) (80 * random()); String lastName =
* lastNameArray[lastPos1]; if (lastLen == 2) { int lastPos2 = (int) (80 *
* random()); lastName = lastName + lastNameArray[lastPos2]; }
*/
for (int i = 0; i < lastLen; i++) {
int lastPos = (int) (80 * random());
name.append(lastNameArray[lastPos]);
}
return name.toString();
} /**
* @description 随机生成5~11位的QQ号。
* @return 生成的QQ号。
*/
public static String getQq() {
char[] numArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
int qqLen = (int) (7 * random()) + 5; // qq号长度可能为5~11位
StringBuilder qq = new StringBuilder();
for (int i = 0; i < qqLen; i++) {
int qqPos = (int) (10 * random());
qq.append(numArray[qqPos]);
}
return qq.toString();
} /**
* @description 随机选择9种方向之一。
* @return 选择的学习方向。
*/
public static String getMajor() {
String[] majorArray = { "css", "js", "android", "ios", "java", "op", "pm", "ui", "qa" };// 共有9种方向
int majorPos = (int) (9 * random());
return majorArray[majorPos];
} /**
* @description 随机生成的入学时间,时间范围在2016.1.1~2017.12.31。
* @return 生成的入学时间。
*/
public static String getEntryTime() {
// 先确定2016.1.1和2017.12.31对应的毫秒数,在此范围内生成long随机数,然后根据该随机数生成java.sql.Date,再toString。
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(2016, 0, 1);
long minMillis = calendar.getTimeInMillis();
calendar.set(2018, 0, 1);
long maxMillis = calendar.getTimeInMillis();
long millis = (long) ((maxMillis - minMillis) * random()) + minMillis;
return (new Date(millis)).toString();
} /**
* @description 随机选择10所学校之一。
* @return 选择的学校。
*/
public static String getSchool() {
String[] schoolArray = { "北京大学", "清华大学", "武汉大学", "复旦大学", "浙江大学", "上海交通大学", "南京大学", "中国人民大学", "解放军国防科学技术大学",
"吉林大学" };
int schoolPos = (int) (10 * random());
return schoolArray[schoolPos];
} /**
* @description 随机生成的学号,取值范围在1~2147483647 (int最大正值)。
* @return 生成的学号。
*/
public static int getJnshuId() {
return (int) (Integer.MAX_VALUE * random()) + 1;
} /**
* @description 随机生成的日报链接:http://www.jnshu.com/daily/xxxx(int型数字,取值范围:1~2147483647
* (int最大正值))。
* @return 生成的日报链接。
*/
public static String getDailyUrl() {
return "http://www.jnshu.com/daily/" + getJnshuId();
} /**
* @description 固定为:好好学习,天天向上!
* @return 生成的口号
*/
public static String getDesire() {
return "好好学习,天天向上!";
} /**
* @description 随机生成师兄姓名,通过调用getName实现。
* @return 生成的师兄姓名
*/
public static String getJnshuBro() {
// 插入大量数据时,考虑到效率,此处可能会改为固定姓名。
return getName();
} /**
* @description 在三种途径中选择一个。
* @return 选择的了解途径。
*/
public static String getKnowFrom() {
String[] knowFromArray = { "知乎", "朋友推荐", "传单/广告" };
int knowFromPos = (int) (3 * random());
return knowFromArray[knowFromPos];
}
}
简单测试插入10条数据的结果如下: