设计数组工具类、日期工具类;线程模拟多窗口售票流程;总结内部类访问方式;区分数值和字符串并排序;猜四位数小游戏


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();
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值