java work week-two
1. 设计可存储不同长度、兼容多种类型数组工具类
可以参照工具类中有的方法来写。
用泛型的:
class ArrayTool<E> {
private static final int DEFAULT_CAPACITY = 10; // 默认数组空间容量为10
private Object[] objArr; // 初始数组
private int size = 0; // 数组中元素个数
public ArrayTool() {
objArr = new Object[DEFAULT_CAPACITY];
}
public ArrayTool(int capacity) {
objArr = new Object[capacity];
}
// 添加元素
public boolean add(E element) {
this.isCapacity(size+1); // 判断数组容量是否够用,不够扩容
objArr[size++] = element; // 添加元素入数组
return true;
}
// 判断数组容量是否够用
private void isCapacity(int capacity) {
if(capacity > objArr.length) { // 若不够用,需要扩容
this.larger(capacity);
}
}
// 扩容
private void larger(int capacity) {
int oldCapacity = objArr.length;
int newCapacity = oldCapacity + (oldCapacity>>1); // oldCapacty*1.5
if(newCapacity < capacity) {
newCapacity = capacity;
}
// 扩容后,将就数组的内容复制到新数组空间中
objArr = this.copyOf(objArr, newCapacity);
}
// 复制原数组内容到新数组
private Object[] copyOf(Object[] oldArray, int capacity) {
Object[] newArray = new Object[capacity];
for(int i=0; i<objArr.length; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}
// 获取数组中元素
public E get(int index) {
this.rangeCheck(index); // 判断索引是否在数组范围内
return (E)objArr[index];
}
// 判断索引是否在数组范围内
private void rangeCheck(int index) {
if(index<0 || index>this.size) {
throw new BoxIndexOutOfBoundsException("your index:" + index + ",the size of the array" + size);
}
}
// 删除元素
public E remove(int index) {
this.rangeCheck(index); // 检查索引是否在数组范围内
E eleDel = (E)objArr[index]; // 要删除的元素
// 删除元素
for(int i=index; i<size-1; i++) {
objArr[i] = objArr[i+1];
}
objArr[--size] = null; // 末尾元素清空
return eleDel;
}
// 查看真实数组长度
public int getLength() {
return objArr.length;
}
// 查看数组中有效元素个数
public int getSize() {
return this.size;
}
// 查看数组中所有元素
public void showElement() {
for(int i=0; i<this.getSize(); i++) {
System.out.print(objArr[i]+",");
}
}
}
// 自定义异常类
class BoxIndexOutOfBoundsException extends RuntimeException{
public BoxIndexOutOfBoundsException() {}
public BoxIndexOutOfBoundsException(String msg) {
super(msg); // msg提供给父类
}
}
public class OneArray {
public static void main(String[] args) {
ArrayTool<Integer> arrInt = new ArrayTool<Integer>(5);
for(int i=0; i<5; i++) {
arrInt.add(i);
}
System.out.println("length:" + arrInt.getLength() + ",size:" + arrInt.getSize());
arrInt.showElement();
arrInt.remove(3);
System.out.println("length:" + arrInt.getLength() + ",size:" + arrInt.getSize());
arrInt.showElement();
System.out.println();
ArrayTool<Float> arrFloat = new ArrayTool<Float>(5);
for(int i=0; i<5; i++) {
arrFloat.add(i+0.05f);
}
System.out.println("length:" + arrFloat.getLength() + ",size:" + arrFloat.getSize());
arrFloat.showElement();
arrFloat.remove(3);
System.out.println("length:" + arrFloat.getLength() + ",size:" + arrFloat.getSize());
arrFloat.showElement();
}
}
或者用Object的:
import java.util.Arrays;
class MyArrayList {
private Object[] objects;
private int size = 0; // 假定的容量
private int maxSize = 10; // 当前最大容量
public MyArrayList() {
objects = new Object[maxSize];
}
/**
* 增(添加数据,注意扩容)
* @param object
*/
public void add(Object object) {
if(size == maxSize) { // 数组扩容
objects = cloneMax(new Object[maxSize + 10], objects);
}
objects[size] = object;
size++;
}
/**
* 删
* @param index
*/
public void remove(int index) {
if(index < size) {
for(int i = index; i < size - 1; i++) {
objects[i] = objects[i + 1];
}
size--;
}
}
/**
* 改
* @param index
* @param object
*/
public void set(int index, Object object) {
if(index < size) {
objects[index] = object;
}
}
/**
* 查,根据下标查询
* @param index
* @return
*/
public Object get(int index) {
return index < size ? objects[index] : null;
}
public Object[] toArray() {
Object[] temp = new Object[size];
for(int i = 0; i < temp.length; i++) {
temp[i] = objects[i];
}
return cloneMin(objects, new Object[size]);
}
public int size() {
return size;
}
@Override
public String toString() {
return Arrays.toString(this.toArray());
}
/**
* 将小的数组中的元素复制进大的数组
* @param maxArray
* @param minArray
* @return
*/
private Object[] cloneMax(Object[] maxArray, Object[] minArray) {
for(int i = 0; i < minArray.length; i++) {
maxArray[i] = minArray[i];
}
return maxArray;
}
/**
* 将大的数组中的元素复制进小的数组
* @param maxArray
* @param minArray
* @return
*/
private Object[] cloneMin(Object[] maxArray, Object[] minArray) {
for(int i = 0; i < minArray.length; i++) {
minArray[i] = maxArray[i];
}
return minArray;
}
}
public class OneNeusoft {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add(3.0f);
list.add(4.5f);
System.out.println(list.toString());
}
}
2.控制台随机输入数值或字符串,区分出数值和字符串,从小到大输出。要求:个数、类型不限;去除重复
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class TwoNeusoft {
public static void main(String[] args) {
Set<Integer> intSet = new HashSet<>();
Set<String> strSet = new HashSet<>();
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字或字符串(空格分隔,回车提交):");
String string = sc.nextLine();
sc.close();
String[] str = string.split(" "); // 按空格分隔
// 数据分类放入set中,去除重复
for(String s : str) {
if(s.matches("^-?[0-9]+$")) {
intSet.add(Integer.parseInt(s));
} else {
strSet.add(s);
}
}
Object[] intArray = intSet.toArray();
Object[] strArray = strSet.toArray();
Arrays.sort(intArray);
Arrays.sort(strArray);
System.out.println("数字排序后:" + Arrays.toString(intArray));
System.out.println("字符串排序后:" + Arrays.toString(strArray));
}
}
3.设计日期工具类(兼容jdk5-8)
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
class DateUtils {
// 固定格式同final。需要统一格式的,要定好
public static final String DATE_FORMAT_YMD = "yyyy-MM-dd";
/**
* 获得现在时间
* @return
*/
// static静态方法,类中被频繁访问的方法用static,可以类名.方法名调用,方便
public static String now() {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
return sdf.format(new Date());
}
/**
* 默认输出yyyy-MM-dd
* @param time
* @return
*/
public static String formatDateToString(Date time) {
// Date旧的
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_YMD);
return sdf.format(time);
}
// 完成同一功能的用重载
public static String formatDateToString(LocalDate localDate) {
// LocalDate 新的 java8
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
return dtf.format(localDate);
}
/**
* 按照指定格式输出
* @param time
* @param format
* @return
*/
public static String formatDateToString(Date time, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(time);
}
public static String formatDateToString(LocalDate localDate, String format) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format);
return dtf.format(localDate);
}
/**
* 根据日期获得是星期几
* @param date
* @return
*/
public static String getWeekOfDate(Date date) {
String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
if(w < 0)
w = 0;
return weekDays[w];
}
}
public class ThreeNeusoft {
public static void main(String[] args) {
System.out.println(DateUtils.now());
System.out.println(DateUtils.getWeekOfDate(new Date()));
}
}
4.总结内部类访问方式
内部类特性
普通类的访问权限修饰符:
default、public
内部类的访问权限修饰符:
default、public、protected、private
以Outer为外部类,Inner为内部类。
class Outer {
class Inner {
}
}
在Outer内访问Inner,只需:
Inner in = new Inner();
在Outer外访问Inner,必须:
Outer o = new Outer(); // 实例化外部类
// 内部类前加前缀,哪个类里的内部类
Outer.Inner oi = o.new Inner(); // 实例化内部类
静态内部类
用static标识的内部类为静态内部类。
静态内部类作为外部类的静态成员,不能访问外部类非静态成员。
非静态内部类只能定义非静态成员,而静态内部类可以定义静态成员和非静态成员。
使用Outer.Inner inn = new Outer.Inner()方式实例化静态内部类。
非静态内部类不可以使用这种方式实例化。
局部内部类
在一个类的方法中或程序块内定义的内部类。
class A{
int a;
public void method() {
}
// 类中定义的内部类
class B {
}
}
class C {
int a;
public void method(int c) {
int b = 0;
// 局部内部类
class B {
}
}
}
需要写很多代码时,为了方便,使用局部内部类。
局部内部类,调用外面final成员。
局部内部类一般不让其它类调用,只是当前方法用。
还有比较细的版本…
// 内部类指将一个类定义在另一个类的内部。内部类可分为静态内部类、成员内部类、局部内部类和匿名内部类。
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
// 静态内部类定义方法:
class OutClass1{
static class InnerClass {
}
}
/*
静态内部类被声明为static的内部类。
它不依赖于外部类实例而被实例化,而通常的内部类需要在外部类实例化后才能实例化。
静态内部类不能与外部类有相同的名字,而且不能访问外部类的普通成员变量,只能访问外部类中的静态成员和静态方法。
*/
// 成员内部类定义方法:
class OutClass2{
class InnerClass{
}
}
/*
静态内部类去掉关键字static就变成了成员内部类。
成员内部类可以随便引用外部类的成员变量和方法,无论其实静态和非静态。
但是成员内部类是在外部类实例化后才能够被实例化,因此不可以定义静态的属性和方法。
需要注意的是:非静态内部类中不能有静态成员。
*/
// 局部内部类定义方法:
class OutClass3{
public void fuctionName(){
class InnerClass{
}
}
}
/*
局部内部类指定义在一个代码块中的类,它的作用范围为所在的代码块,是内部类中最少是用的一种内部类。
局部内部类类似于局部变量,不能被public、protected、private以及static修饰,只能访问方法中定义为final类型的局部变量。
*/
// 匿名内部类
class MyFrame extends Frame { // 外部类
public MyFrame(){
addWindowListener(new WindowAdapter(){ // 匿名内部类
public void windowClosing(WindowEvent e){
dispose();
System.exit(0);
}
}
);
}
}
/* 匿名内部类是一种没有类名的内部类,没有构造函数,它必须继承其他类或者其他接口。
他一般应用于GUI编程中实现事件处理等。
*/
// 内部类与外部类的互访使用小结
// 内部类访问外部类
// 里面的可以自由访问外面的,规则和static一样。(访问非静态时必须先创建对象)
// 非静态内部类的非静态方法-直接访问
class Outter1 {
int i = 5;
static String string = "Hello";
class Inner1{
void Test1 () {
System.out.println(i);
System.out.println(string);
}
}
}
// 静态内部类的非静态方法
// 因为静态方法访问非静态外部成员需先创建实例,所以访问i时必须先new外部类
class Outter2 {
int i = 5;
static String string = "Hello";
static class Inner2{
void Test1 () {
System.out.println(new Outter2().i);
System.out.println(string);
}
}
}
// 静态内部类的非静态方法
// 因为静态方法访问非静态外部成员需先创建实例,所以访问i时必须先new外部类
class Outter3 {
int i = 5;
static String string = "Hello";
static class Inner2{
void Test1 () {
System.out.println(new Outter3().i);
System.out.println(string);
}
}
}
// 静态内部类的静态方法-规则如上
class Outter4 {
int i = 5;
static String string = "Hello";
static class Inner2{
static void Test2 () {
System.out.println(new Outter4().i);
System.out.println(string);
}
}
}
// 外部类访问内部类
//大方向:因为将内部类理解为外部类的一个普通成员,所以外部的访问里面的需先new一个对象。
// 非静态方法访问非静态内部类的成员-new 内部类对象
class Outter5 {
static void Test2() {
System.out.println(new Outter5().new Inner1().i);
}
class Inner1{
int i = 5;
// static String string = "Hello"; 定义错误!
}
}
// 静态方法访问非静态内部类的成员
// 静态方法Test2访问非静态Inner1需先new外部类,继续访问非静态成员i需先new内部类
// 所以访问规则为:new Outter().new Inner1().i。
class Outter6 {
static void Test2(){
System.out.println(new Outter6().new Inner1().i);
}
class Inner1{
int i = 5;
// static String string = "Hello"; 定义错误!
}
}
// 非静态方法访问静态内部类的成员
// 先“外部类.内部类”访问至内部类。
// 若访问非静态成员,则需先new再访问;若访问静态成员,则可直接访问。
class Outter7 {
void Test2() {
Outter7.Inner2 inner2 = new Outter7.Inner2();
System.out.println(inner2.i);
System.out.println(inner2.string);
System.out.println(Outter7.Inner2.string);
}
static class Inner2{
int i = 5;
static String string = "Hello"; // 定义错误!
}
}
// 非静态方法访问非静态内部类的成员
// 先“外部类.内部类”访问至内部类,再new即可访问静态成员。
class Outter8 {
void Test1(){
Outter8.Inner1 inner2 = new Outter8.Inner1();
System.out.println(inner2.i);
}
class Inner1{
int i = 5;
// static String string = "Hello"; 定义错误!
}
}
// 匿名内部类
// 匿名内部类访问外部成员变量时,成员变量前应加final关键字。
// final int k = 6;
5.设计小游戏-控制台输入一个四位不重复数
控制台输入一个四位不重复数。输入数字后,如果数位上给的提示是“A”,说明既猜对了数字,也猜对了数位;如果数位上给的提示是“B”,说明猜对了数字,但数位没猜对;如果数位上给的提示是“—”,那么证明你猜的数字根本不会出现在这个四位数中。
例如: 1234,AB–,说明第一位是1,数字2存在,但不第二位上
要求:四位数后台随机生成,限时一分钟,可猜30次,最终提示成功或失败。
这道题需要我们可爱的多线程啦…
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.Set;
public class FiveGame {
private boolean flag = true; //
/**
* 得到一个0-9的随机数
* @return
*/
private static int getRandomNumber() {
return (int) ((Math.random() * 100) % 10);
}
/**
* 得到一个四位无重复数字的数
* @return
*/
private static String getNumber() {
Set<Integer> set = new HashSet<Integer>();
while (true) {
int a = getRandomNumber();
set.add(new Integer(a));
if(set.size() > 3)
break;
}
int index = (int) ((Math.random() * 100) % 4);
if(index==0) {
index+=1;
}
Integer[] arr = new Integer[set.size()];
set.toArray(arr);
String s = "";
if(arr[0].intValue()==0){ // 如果第一位是0,则随机和后面三位交换
Integer temp = arr[0];
arr[0] = arr[index];
arr[index] = temp;
}
for(int i=0;i<arr.length;i++){
s += arr[i].intValue();
}
return s;
}
/**
* 根据用户输入的四位数判断游戏得到的结果
* @param number 系统生成的四位数
* @param num 用户输入的四位数
* @return
*/
private static String game(String number, String num) {
String str = "";
for(int i=0; i<number.length(); i++) {
str += every(number, num.charAt(i), i);
}
return str;
}
/**
*
* @param number 系统生成的四位数
* @param a 用户输入四位数中的第i位
* @param i
* @return
*/
private static String every(String number, char a, int i) {
String c = "";
int position = number.indexOf(a);
if(position != -1) {
if(position == i) {
return "A";
} else {
return "B";
}
} else {
return "-";
}
}
public void startGame() {
String number = getNumber(); // 系统生成的四位随机数
Thread thread = new Thread() {
public void run() {
System.out.println("Thread");
Scanner sc = new Scanner(System.in);
System.out.println("游戏开始!\n请输入四位数:");
int count = 0;
while (flag) {
if(count >= 30) {
System.out.println("次数已用尽...");
System.exit(0);
}
String numStr = String.valueOf(sc.nextInt()); // 用户输入
if(game(number, numStr).equals("AAAA")) {
System.out.println("恭喜您,猜对了!");
System.exit(0);
} else {
System.out.println(game(number, numStr));
}
count++;
}
}
}; // end Thread
thread.start();
try {
Thread.sleep(1000 * 60);
flag = false;
if(thread.isAlive()) {
System.out.println("对不起,时间到了,游戏结束");
}
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
FiveGame fg = new FiveGame();
fg.startGame();
}
}
写的还不完善…(懒得写了)->_->
待改善:用户输入的问题(不是四位不同的数)
附加题:使用线程模拟多窗口售票流程(不可出现重复票)
class SaleTickets implements Runnable {
private int ticketCount = 100; // 总的票数,进程之间共享
Object lock = new Object(); // 锁
/**
* 卖票,操作共享数据,用同步代码块包裹
*/
public void sellTicket() {
synchronized (lock) {
if(ticketCount > 0) {
ticketCount--;
System.out.println(Thread.currentThread().getName() + "正在卖票,还剩" + ticketCount + "张票");
} else {
System.out.println("票已卖完!");
return;
}
}
}
@Override
public void run() {
while(ticketCount > 0) {
sellTicket();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MoreNeusoft {
public static void main(String[] args) {
SaleTickets st = new SaleTickets();
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
Thread t4 = new Thread(st, "窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}