SDKD Java实验四 容器

实验目的

  1. 熟悉容器类库中常用类的使用方法。
  2. 使用常用容器类解决一般性的应用问题。

实验内容

学生排序

编写一个程序,用户可以从键盘录入若干个学生的姓名和分数(程序每次提示用户输入“Y”或“N”决定是否继续录入学生信息,如果用户输入“N”则用户输入完毕。输入的“Y”、“N”不区分大小写)。用户录入完毕后,程序按成绩由高到低的顺序输出学生的姓名和分数(姓名和分数之间用一个空格分割)。【说明:键盘输入可以使用Scanner类】

代码

Main.java

import java.util.Objects;
import java.util.Scanner;
import java.util.TreeSet;

public class Main {
    static final Scanner cin = new Scanner(System.in);
    public static void main(String[] args) {
    // write your code here
        var set =  new TreeSet<Student>();
        /*
            流程模拟
        */
        while(true) {
            System.out.print("是否添加一个学生?(y/n)");
            String option = cin.next();
            if(Objects.equals(option, "Y") || Objects.equals(option, "y")) {
                set.add(new Student(cin.next(),cin.nextDouble()));
            }else if(Objects.equals(option, "N") || Objects.equals(option, "n"))
                break;
            else
                System.out.print("输入错误,");
        }
        /*
            输出
        */
        for(Student tmp : set)
            System.out.println(tmp);
    }
}

Student.java

/*
学生类:存储学生姓名 成绩,自带排序功能
*/
public class Student implements Comparable<Student>{

    private String name;
    private double score;
    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString() {
        return name + " " + score;
    }
    @Override
    public int compareTo(Student other) {
        return -Double.compare(score, other.score);
    }
}

网上购物车

用HashMap模拟一个网上购物车。要求:从键盘输入n本书的名称、单价、购买数量,将这些信息存入一个HashMap,然后将该HashMap作为参数调用方法getSum(HashMap books),该方法用于计算书的总价并返回。【说明:键盘输入可使用Scanner类】

代码

Main.java

import java.util.Scanner;

public class Main {
    private static final Scanner cin = new Scanner(System.in);

    public static void main(String[] args) {
        // write your code here
        //程序输入部分
        System.out.print("请输入你要购买的书的种类数:");
        int n = cin.nextInt();
        ShoppingCart cart = new ShoppingCart();
        for (int i = 1; i <= n; ++i) {
            System.out.println("请输入你要购买的第" + i + "种书的名称、单价、购买数量(以空格分隔)");
            Book item = new Book(cin.next(), cin.nextDouble());
            cart.add(item, cin.nextInt());
        }
        //输出
        System.out.print("你本次购物总计消费" + cart.getSum(cart.getData()) + "元");
    }
}

/*
测试数据:
4
a 1 2
b 2 2
c 1 1
d 1 0
*/

Book.java

import java.util.Objects;
/*
    图书类:存储图书的名称和价格
*/
public class Book {
    private String name;
    private double price;
    public String getName() {
        return name;
    }
    public Book(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public double getPrice() {
        return price;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Double.compare(book.price, price) == 0 &&
                Objects.equals(name, book.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, price);
    }
}

ShoppingCart.java

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class ShoppingCart {
    private HashMap<Book, Integer> data = new HashMap<Book, Integer>();

    //向购物车添加商品
    public Integer add(Book book, int num) {
        return data.put(book, num);
    }
    //向购物车添加商品
    public void showAll() {
        Iterator it = data.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Book book = (Book) entry.getKey();
            int num = (int) entry.getValue();
            System.out.println(book.getName() + " " + book.getPrice() + " " + num);
        }
    }
    /*
        提取购物车的数据
    */
    public HashMap<Book, Integer> getData() {
        return data;
    }

    /*
        getSum() 计算购物车内的商品总价
        既可以计算本购物车的总价,也可以计算外部购物车数据的总价
    */
    
    public Double getSum(HashMap<Book, Integer> all) {
        Double sum = 0.0;
        Iterator it = all.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Book book = (Book) entry.getKey();
            int num = (int) entry.getValue();
            sum += (book.getPrice() * num);
        }
        return sum;
    }
    public Double getSum() {
        Double sum = 0.0;
        Iterator it = data.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Book book = (Book) entry.getKey();
            int num = (int) entry.getValue();
            sum += (book.getPrice() * num);
        }
        return sum;
    }
}

30选7

写一个彩票的模拟程序:30选7。随机(1~30之间)生成7个随机数,注意不能重复。然后从键盘输入7个数,对比7个数是否与随机数有相同的。最后显示“中了几个号”。同时,如果中了7个号,显示一等奖;如果中了6个号,显示二等奖;如果中了5个号,显示三等奖。要求:首先在注释中写出程序的实现思想,特别是程序所使用的数据结构,然后写出Java实现代码。【说明:键盘输入可以使用Scanner类】

代码

Main.java

import java.util.*;

public class Main {
    //创建Scanner 和 彩票机对象实例
    static final Scanner cin = new Scanner(System.in);
    private static LotteryMachine lotteryMachine = new LotteryMachine();

    public static void main(String[] args) {
        // write your code here
        
        
        //输入 开奖 展示
        Set<Integer> numbers = getInput();
        int prices = lotteryMachine.lottery(numbers);
        Set<Integer> ans = lotteryMachine.getWinNumber();
        
        /*
            展示抽奖数据
        */
        System.out.print("本期中奖号码是:");
        for (int i : ans) {
            System.out.print(i + " ");
        }
        System.out.print('\n');
        //System.out.println("price: " + prices);
        System.out.println("您猜中了" + prices + "个数");
        int awardLevel = LotteryMachine.SELECT_NUMBER - prices;
        //System.out.println("awardLevel: " + awardLevel);
        if (awardLevel < LotteryMachine.AWARD_LEVELS.length)
            System.out.println("恭喜,您获得了" + LotteryMachine.AWARD_LEVELS[awardLevel]);
        else
            System.out.println("很遗憾,您未中奖,再接再厉吧!");

    }
    /*
        程序的输入及其预处理方法
    */
    private static Set<Integer> getInput() {
        
        List<Integer> list = new ArrayList<>();
        Set<Integer> set = new HashSet<>();
        while (true) {
            // 每次输入前刷新中奖值
            lotteryMachine.refresh();
            list.clear();
            
            //程序在此获得用户输入
            System.out.println("请在1~" + LotteryMachine.RANGE + "之间选择" + LotteryMachine.SELECT_NUMBER + "个不同的数:");
            while (list.size() < LotteryMachine.SELECT_NUMBER)
                list.add(cin.nextInt());
            
            set.addAll(list);
            /*
                输入预处理部分
            */
            if (set.size() < LotteryMachine.SELECT_NUMBER) {
                //用户输入重复数字
                System.out.println("输入错误:你选择的数字中不同的数不足" + LotteryMachine.SELECT_NUMBER + "个");
            } else {
                /*
                    在此判断用户输入是否在指定范围
                */
                int invalidCount = 0;
                for (int i : set)
                    if (i > LotteryMachine.RANGE || i < 1) {
                        ++invalidCount;
                        System.out.println("输入错误:你选择的数字中有不在1~" + LotteryMachine.RANGE + "之间的数");
                    }
                //输入符合规则    
                if (invalidCount == 0)
                    return set;
            }
        }
    }
}

LotteryMachine.java

import java.util.HashSet;
import java.util.Set;

/*
      彩票机类
    * 可自定义抽奖范围 一次抽出数字个数 奖项的个数及名称
    * */
    

class LotteryMachine {
    //抽奖范围
    public static final int RANGE = 30;
    //抽出数字个数
    public static final int SELECT_NUMBER = 7;
    //奖项设置
    public static final String[] AWARD_LEVELS = {"一等奖", "二等奖", "三等奖"/*, "四等奖", "五等奖", "六等奖", "七等奖"*/};
    //TODO:创建中奖数的存储空间
    private Set<Integer> data = new HashSet<>();
    public LotteryMachine() {
        //创建彩票机时进行初始化刷新
        this.refresh();
    }
    /*
        刷新彩票机的的中奖数据
    */
    public void refresh() {
        data.clear();//TODO:清空彩票机中奖数据
        do {
            data.add(getRandomNumber());
        } while (data.size() != SELECT_NUMBER);
    }
    /*
        刷新彩票机的的中奖数据
    */
    public int lottery(Set<Integer> selected) {
        int num;
        selected.addAll(data);
        num = 2 * SELECT_NUMBER - selected.size();
        return num;
    }
    /*
        查看本期的中奖号码
    */
    public Set<Integer> getWinNumber() {
        final Set<Integer> result = new HashSet<>(data); //TODO :一定要创建新的对象,否则后续刷新将改变getWinNumber()的结果
        this.refresh();
        return result;
    }
    /*
        获取一个符合彩票范围的随机数
    */
    static private int getRandomNumber() {
        double random = Math.random();
        return 1 + (int) (random * RANGE);
    }
}

笛卡尔积

设计一个类的方法,其输入是两个字符串的集合(每个集合中的字符串有相同的意义,例如,一个全是姓名的字符串,一个全是班级的字符串),打印出这两个集合的笛卡尔乘积。

扫描二维码关注公众号,回复: 7712394 查看本文章

代码

Main.java

import java.util.*;

public class Main {
    static final Scanner cin = new Scanner(System.in);

    public static void main(String[] args) {
        // write your code here
        int n;
        CartesianProductCalculator<Object> calculator = new CartesianProductCalculator<Object>();
        /*
            数据的填入
        */
        String[] str1 = {"小明", "小红"};
        String[] str2 = {"一班", "二班"};
        List<Set<Object>> list = new ArrayList<>();
        list.add(new HashSet<>(Arrays.asList(str1)));
        list.add(new HashSet<>(Arrays.asList(str2)));

        /**
         * 该编写方式实现了求n个任意集合的笛卡尔积
         * 下方已注释代码块提供了String Integer Double 求笛卡尔积的实例
         */

/*
        Integer[] str3 = {1, 2};
        Double[] str4 = {99.5, 86.4};
        String[] str5 = {"A"};
        list.add(new HashSet<>(Arrays.asList(str3)));
        list.add(new HashSet<>(Arrays.asList(str4)));
        list.add(new HashSet<>(Arrays.asList(str5)));
*/
        calculator.inputData(list);
        //展示结果
        Set<List<Object>> ans = calculator.getAns();
        for (List<Object> i : ans) {
            for (int j = 0; j < i.size(); ++j) {
                if (j != 0) System.out.print(" ");
                System.out.print(i.get(j));
            }
            System.out.print("\n");
        }
    }
}

CartesianProductCalculator.java

import java.util.*;

/*
    笛卡尔积计算器
*/

class CartesianProductCalculator<E> {
    List<Set<E>> data;/* = new List<>();*/
    Set<List<E>> ans;
    // 通过传参输入数据
    public void inputData(List<Set<E>> data)
    {
        this.data = new ArrayList<Set<E>>(data);
    }
    /*
        通过两两求笛卡尔积的方式,求任意数量集合的笛卡尔积
    */
    private void calculate(){
        ans = new HashSet<List<E>>();
        Iterator it = data.iterator();
        if(it.hasNext()){
            Set<E> tmp = data.get(0);
            for(E e : tmp){
                List<E> node = new ArrayList<E>();
                node.add(e);
                ans.add(node);
            }
        }
        for(int i = 1; i < data.size(); ++i)
        {
            List<E> first = new ArrayList<E>(data.get(i));
            List<List<E>> second = new ArrayList<List<E>>(ans);
            ans.clear();
            for(E fir : first)
                for(List<E> sec : second)
                {
                    List<E> node = new ArrayList<E>(sec);
                    node.add(fir);
                    ans.add(node);
                }
        }
    }
    // 计算并返回结果
    public Set<List<E>> getAns(){
        calculate();
        return ans;
    }
}

保皇游戏

作者:张峰老师
单位:山东科技大学

模拟保皇游戏开始的发牌过程。规则:4副扑克,5个玩家。1)有一个大王标记为皇上。每次发牌时,所发牌中有该大王的玩家是皇上。2)皇帝选择侍卫(也叫保儿、腿子,游戏过程中与皇帝一伙):作为皇上的玩家从自己的牌中选择一张拥有相同三张(点数和花色都相同)的一张牌(不能是2、3、大小王),其他四个玩家中有这张牌的就是侍卫。例如,皇上有三个红桃5,其他四个玩家中有红桃5的玩家就是侍卫。特殊情况是:1)皇上有一套四张牌相同的点数的牌,皇帝可以自己做侍卫;2)皇帝没有满足要求的牌,无法获得侍卫。程序要求:程序启动后生成5个玩家,并自动给他们发牌。然后输出:1)皇帝和侍卫的名字及其手里的牌(每张牌输出为“花色”+“点数”,如红桃5,牌之间用“,”分割),并按照大王、小王、2、A、K、Q、J、10、9、8、7、6、5、4、3的顺序排列,相同点数但不同花色的牌要把相同花色的牌放在一起;2)那张作为侍卫所特有的牌(“花色”+“点数”)。如果无法得到侍卫,则程序输出相应的提示。例如,程序运行后输出如下的结果:

皇帝是:玩家1
皇帝的牌是:[皇上, 小王, 小王, 小王, 小王, 方片2, 黑桃2, 黑桃A, 黑桃A, 红桃A, 方片K, 梅花K, 黑桃K, 红桃K, 梅花Q, 梅花Q, 黑桃Q, 方片J, 方片J, 方片J, 红桃J, 梅花9, 黑桃9, 黑桃9, 方片8, 梅花8, 红桃8, 梅花7, 黑桃7, 黑桃7, 红桃7, 梅花6, 梅花6, 黑桃6, 黑桃6, 方片5, 梅花5, 黑桃5, 黑桃5, 梅花4, 梅花4, 梅花4, 方片3, 红桃3]

侍卫对应的牌是:方片J

侍卫是:玩家2

侍卫的牌是:[方片2, 黑桃2, 红桃2, 方片A, 方片K, 梅花K, 梅花K, 黑桃K, 红桃K, 红桃K, 黑桃Q, 红桃Q, 方片J, 方片10, 黑桃10, 红桃10, 红桃10, 红桃10, 方片9, 红桃9, 方片8, 梅花8, 梅花8, 黑桃8, 黑桃8, 黑桃8, 红桃8, 红桃8, 方片7, 黑桃7, 黑桃7, 方片6, 黑桃6, 黑桃5, 梅花4, 黑桃4, 红桃4, 红桃4, 方片3, 梅花3, 黑桃3, 红桃3, 红桃3]

代码

Main.java

public class Main {
    public static void main(String[] args) {
    // write your code here
        Game game = new Game();
        game.run();
    }
}

Game.java

import java.util.Set;

/*
    游戏类
*/

public class Game {
    //默认的玩家数量
    static final int DEFAULT_PLAYER_NUMBER = 5;
    //默认几副牌
    static final int DEFAULT_DECK_NUMBER = 4;
    //玩家数
    private int playerNumber;
    //牌的数量
    private int deckNumber;
    //发牌员对象实例
    private Dealer dealer;
    //玩家对象实例
    private Player[] players;

    public Game() {
        //创建玩家
        this.playerNumber = DEFAULT_PLAYER_NUMBER;
        players = new Player[playerNumber];
        //生成牌堆
        this.deckNumber = DEFAULT_DECK_NUMBER;
        dealer = new Dealer(deckNumber);
        
        // 创建数组不会自动生成对象
        for (int i = 0; i < players.length; ++i)
            players[i] = new Player();

    }

    public Game(int playerNumber, int deckNumber) {
        this.playerNumber = playerNumber;
        this.deckNumber = deckNumber;
        dealer = new Dealer(deckNumber);
        players = new Player[playerNumber];
        // 创建数组不会自动生成对象
        for (int i = 0; i < players.length; ++i)
            players[i] = new Player();
    }
    /*
        询问各玩家是不是皇帝
    */
    private int findEmperor() {
        int i;
        for (i = 0; i < players.length; ++i)
            if (players[i].isEmperor())
                break;
        return i;
    }
    /*
        游戏运行
    */
    public void run() {
        //发牌员发牌
        dealer.licensing(players);
        //获取皇帝
        int emperorId = findEmperor();
        System.out.println("玩家" + (emperorId + 1) + "是皇帝");
        System.out.println("手牌是" + players[emperorId].cardsToString());
        
        Set<PokerCard> s = players[emperorId].getEmperorCard(deckNumber);
    
        /*
            展示可选的侍卫,以及侍卫的牌
        */
        
        if (s.size() > 0) {
            System.out.print("可选的侍卫牌有:");
            for (PokerCard card : s)
                System.out.print(" " + card);
            System.out.print('\n');
            for (PokerCard card : s) {
                System.out.print("\n如果你选择" + card + ",那么");
                int i;
                for (i = 0; i < players.length; ++i)
                    if (players[i].getCardCount(card) == 1 || players[i].getCardCount(card) == 4)
                        break;
                if (i == emperorId)
                    System.out.println("你得自保");
                else {
                    System.out.println("你的侍卫是玩家" + (i + 1));
                    System.out.print("他的手牌是:");
                    System.out.println(players[i].cardsToString());
                }
            }
        } else {
            System.out.println("很遗憾,你没有可选的侍卫牌");
        }
    }
}

Dealer.java

import java.util.*;

public class Dealer {
    private Queue<PokerCard> cardsQueue = new LinkedList<PokerCard>();
    private int deckNumber;

    public Dealer(int deckNumber) {
        
        this.deckNumber = deckNumber;
        refreshQueue();
    }

    public void setDeckNumber(int deckNumber) {
        //设置要发几副牌
        this.deckNumber = deckNumber;
        refreshQueue();
    }

    public void refreshQueue() {
        //刷新发牌队列
        cardsQueue.clear();
        List<PokerCard> cards = new LinkedList<PokerCard>();
        for (int i = 0; i < this.deckNumber; ++i)
            cards.addAll(makePokercards());
        //产生皇帝,取出发牌队列中的第一个大王,使其变成皇帝
        cards.set(cards.indexOf(new PokerCard(PokerCard.BIG_JOKER_INDEX, PokerCard.JOKER_POINT))
                , new PokerCard(PokerCard.EMPEROR_INDEX, PokerCard.JOKER_POINT));
        //洗牌
        Collections.shuffle(cards);
        cardsQueue.addAll(cards);
    }

    public void licensing(Player... players) {
        //发牌
        while (!cardsQueue.isEmpty())
            for (Player player : players) {
                if (cardsQueue.isEmpty()) break;
                //空指针异常处理
                try {
                    //发牌员将单张的扑克牌发给玩家
                    player.addCard(cardsQueue.poll());
                } catch (NullPointerException e) {
                    System.out.println("空指针异常: " + e);
                }
            }
    }

    private ArrayList<PokerCard> makePokercards() {
        ArrayList<PokerCard> cards = new ArrayList<PokerCard>();
        //生成大王小王
        cards.add(new PokerCard(PokerCard.BIG_JOKER_INDEX, PokerCard.JOKER_POINT));
        cards.add(new PokerCard(PokerCard.SMALL_JOKER_INDEX, PokerCard.JOKER_POINT));
        //生成其他牌
        for (int i = 0; i < 4; ++i)
            for (int j = 0; j < PokerCard.POINT.length; ++j)
                cards.add(new PokerCard(i, j));

        return cards;
    }
}

Player.java

import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;

public class Player {
    //存储有哪些牌
    private Set<PokerCard> handCards = new TreeSet<PokerCard>();
    //存一下都有几张
    private HashMap<PokerCard, Integer> cardsCounter = new HashMap<PokerCard, Integer>();
    boolean emperor = false;

    //通过传参的方式获取一张牌
    public void addCard(PokerCard poll) {
        handCards.add(poll);
        //自己看一下是不是皇帝
        if (poll.getSuit().equals("皇上"))
            emperor = true;
        cardsCounter.merge(poll, 1, Integer::sum);
    }

    //获取某一种牌的张数
    public int getCardCount(PokerCard card) {
        if (cardsCounter.get(card) == null)
            return 0;
        else return cardsCounter.get(card);
    }

    //手里的牌转换成字符串
    public String cardsToString() {
        StringBuilder str = new StringBuilder();
        str.append("[");
        boolean flag = true;
        for (PokerCard card : handCards) {
            for (int i = 0; i < cardsCounter.get(card); ++i) {
                if (flag) flag = false;
                else str.append(", ");
                str.append(card.toString());
            }
        }
        str.append("]");
        return str.toString();
    }

    //告知别人自己是不是皇帝
    public boolean isEmperor() {
        return emperor;
    }

    //看一下自己可以选哪张牌作为侍卫牌
    public Set<PokerCard> getEmperorCard(int deckNumber){
        Set<PokerCard> ret = new TreeSet<PokerCard>();
        for (PokerCard card : handCards)
            if(!card.getPoint().equals("") && !card.getPoint().equals("3") && cardsCounter.get(card) >= (deckNumber - 1))
                ret.add(card);
        return ret;
    }

}

PokerCard.java

import java.util.Objects;

public class PokerCard implements Comparable<PokerCard> {
    //小王花色序号
    static public final int SMALL_JOKER_INDEX = 4;
    //小王花色序号
    static public final int BIG_JOKER_INDEX = 5;
    //王的点数
    static public final int JOKER_POINT = 100;
    //小王花色序号
    static public final int EMPEROR_INDEX = 6;
    //扑克牌的牌面
    static public final String[] SUIT = { "梅花","方片","红桃","黑桃", "小王", "大王", "皇上"};
    static public final String[] POINT = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
    //存储点数和花色
    private int suit, point;

    public PokerCard(int suit, int point) {
        this.suit = suit;
        this.point = point;
    }
    //获取牌的花色点数
    public String getSuit() {
        return SUIT[suit];
    }
    public String getPoint() {
        if (point != JOKER_POINT)return POINT[point];
        else return "";
    }

    @Override
    public String toString() {
        return getSuit() + getPoint();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PokerCard pokerCard = (PokerCard) o;
        return suit == pokerCard.suit && point == pokerCard.point;
    }

    @Override
    public int hashCode() {
        return Objects.hash(suit, point);
    }
    //牌的排序方法
    @Override
    public int compareTo(PokerCard o) {
        if(point == o.point) {
            return -Integer.compare(suit, o.suit);
        }
        else return -Integer.compare(point, o.point);
    }
}

(选做)Xman

Professor Charles Xavier is having a tough time remembering all the different kinds of X-Men, their power and weakness. With the improvement of cerebro his mind can reach anywhere on earth. He decided to build a database of X- men so that he can find them quickly. You will be helping the great professor in this homework.
Edit: The constructor now takes an enemy list instead of just one enemy.
You’ll need to create two classes to store this information. First you’ll need to create the Xman class. It will need the following methods.

Method Features
public Xman(String name, String xname, String power, String weakness, List< String > enemy, Date birthDate, String gender, String DNASequence) The constructor will need to set the appropriate instance variables.
public String getName() This method should return the xname and name concatenated like xname(name).
public String getPower() Return the power
public String getWeakness() Return the weakness.
public List < Xman > getEnemy() Return the enemy Xmen.
public Date getBirthDate() Return the date of birth. You will need to import the package java.util.date
public String getGender() Return the gender.
public String getDNASequence() Return the DNA sequence (if you decide to use print statements for debugging, be aware that this is a really long string).
public boolean equals(Object o) You need override the equals() method, such that two Xman with the same DNA sequence are considered equal.

Because there are lots of X-men, we need a fast way look them up. We’re going to use the hash tables discussed in class to create a way of looking up records by both DNA sequence and name. Make the class XDatabase which will contain two arrays of lists:

List< Xman >[] dnaSeq;

List< Xman >[] nameIndex;

Having a list at each index of the arrays will allow us to handle collisions, by simply adding multiple Records to that spot. You can use linked list or array list whatever you like. (This can be yours/java's default LinkedList /ArrayList)

Java’s base class Object, has the method hashCode(), which returns an int based on the value of that object. It’s important to note that this can return a negative integer, so when you hash it, you’ll need to take the absolute value. So we can figure out the position a record belongs in thednaSeq array by:

int i = Math.abs(xman.getDNASequence().hashCode()) % dnaSeq.length;

Because we’re going to have a large number of X-men in our database, we need to be conscious of memory usage. This means that we won’t create a list at an index, until we store something at that index.
Finally, this is the list of methods you will need to implement in your XDatabase class:

Method Features
public XDatabase(int size) The constructor will initialize your two arrays to be of the specified size. You will also need to keep track of the total number of items in your database, so you should initialize a size variable to 0 in here too.
public Xman add(Xman xman) This method will take in a Xman, and add it both to the dnaSeq and nameIndex arrays in the appropriate places. If a record with the same DNASequence already exists in the database, it should get replaced, and the previous record should be returned. Otherwise return null.
public Xman getByDNASequence(String dnaSeqence) This method will search for a Xman with the specified dnaSequence using your dnaSeq list. It should return null if no record with that dnaSequence exists.
public List< Xman > getByName(String name) This method will search for a Xman based on name, using the nameIndex. Because it is possible for multiple Xman to have the same name, it will return of list of Xman with matching names. If no records match, an empty list should be returned.
public Xman delete(String dnaSeq) This method should delete the Xman with the matching dnaSeq from both indexes, and return that record. If no record is found, it should return null.
public int size() This method should return the number of Xman stored in the database.
public List< Xman > friends(String dnaSeq) Given a dnaSeq of an Xman, find his/her friends. An Xman A is a friend of another Xman B, if and only if A is not in B's enemy List and A is in the enemy list of at least one of the enemys of B. If no friends are found, return empty list.
public List< Xman > partner(String name) Given the name of a Xman, find his/her partner. An Xman A is the partner of another Xman B, if and only if A is not in B's enemy List and A is in the enemy list of all enemies of B. If no partners are found, return empty list. If multiple Xman are found by the same name, concatenate all their partners in the list.
public List< Xman > archrival(String name) Given the name of a Xman, find his/her arch rival. An Xman A is the arch rival of another Xman B, if and only if A is in the enemy list of Band A is in the enemy list of all friends of B. If no arch rivals are found, return empty list. If multiple Xman are found by the same name, concatenate all their arch rivals in the list.

代码

Xman.java

import java.util.*;
public class Xman {
    private String name;
    private String xname;
    private String power;
    private String weakness;
    private List<String> enemy;
    private Date birthDate;
    private String gender;
    private String DNASequence;

    public Xman(String name, String xname, String power, String weakness, List<String> enemy, Date birthDate, String gender, String DNASequence) {
        this.name = name;
        this.xname = xname;
        this.power = power;
        this.weakness = weakness;
        this.enemy = enemy;
        this.birthDate = birthDate;
        this.gender = gender;
        this.DNASequence = DNASequence;
    }

    public String getName() {
        return xname+"("+name+")";
    }

    public String getWeakness() {
        return weakness;
    }

    public List<String> getEnemy() {
        return enemy;
    }

    public Date getBirthDate() {
        return birthDate;
    }

    public String getGender() {
        return gender;
    }

    public String getDNASequence() {
        return DNASequence;
    }

    public int dnaHash() {
        return Math.abs(getDNASequence().hashCode()) % getDNASequence().length();
    }
    
    public int nameHash() {
        return Math.abs(getName().hashCode()) % getName().length();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Xman xman = (Xman) o;
        return Objects.equals(DNASequence, xman.DNASequence);
    }
}

XDatabase.java

import java.util.*;

public class XDatabase {
    private List<Xman>[] dnaSeq;
    private List<Xman>[] nameIndex;
    private int size;

    public XDatabase(int size) {
        this.size = size;
        init();
    }

    public XDatabase() {
        this.size = 0;
        init();
    }

    private void init() {
        dnaSeq = new ArrayList[size];
        nameIndex = new ArrayList[size];
        for (int i = 0; i < size; ++i) {
            dnaSeq[i] = new ArrayList<Xman>();
            nameIndex[i] = new ArrayList<Xman>();
        }
    }

    public Xman add(Xman xman) {
        Xman bak = null;
        int nameId = xman.nameHash() % size;
        int dnaId = xman.dnaHash() % size;
        if (nameIndex[nameId] == null) {
            nameIndex[nameId] = new ArrayList<Xman>();
            nameIndex[nameId].add(xman);
        }else {
            nameIndex[nameId].add(xman);
        }
        if(dnaSeq[dnaId] != null) bak = dnaSeq[dnaId].get(0);
        dnaSeq[dnaId] = new ArrayList<Xman>();
        dnaSeq[dnaId].add(xman);
        return bak;
    }

    private static int dnaHash(String dnaSeqence) {
        return Math.abs(dnaSeqence.hashCode()) % dnaSeqence.length();
    }

    public Xman getByDNASequence(String dnaSeqence) {
        int dnaId = dnaHash(dnaSeqence);
        return dnaSeq[dnaId]==null? null:dnaSeq[dnaId].get(0);
    }

    private static int nameHash(String name) {
        return Math.abs(name.hashCode()) % name.length();
    }

    public List<Xman> getByName(String name) {
        int nameId = nameHash(name);
        return nameIndex[nameId];
    }

    public Xman delete(String dnaSeq) {
        Xman ret = getByDNASequence(dnaSeq);
        for(int i = 0; i < size; ++i){
            if(this.dnaSeq[i].contains(ret))
                this.dnaSeq[i].clear();
            int id;
            if((id = nameIndex[i].indexOf(ret)) != -1)
                nameIndex[i].remove(id);
        }
        return ret;
    }

    public int size() {
        return this.size;
    }

    public List<Xman> friends(String dnaSeq) {
        //要找朋友的Xman
        Xman xmanFind = getByDNASequence(dnaSeq);
        List<Xman> xFriends = new ArrayList<Xman>();
        if(xmanFind == null) return xFriends;
        for(int i = 0; i < size; ++i){
            if(this.dnaSeq[i].size() == 0)continue;
            Xman check = this.dnaSeq[i].get(0);
            if(xmanFind.getEnemy().contains(check.getDNASequence())) continue;
            for(int j = 0; j < xmanFind.getEnemy().size(); ++j){
                Xman enemy = getByDNASequence(xmanFind.getEnemy().get(j));
                if(enemy == null) continue;
                if(enemy.getEnemy().contains(check.getDNASequence()))
                {
                    xFriends.add(check);
                    break;
                }
            }
        }
        return xFriends;
    }

    public List<Xman> partner(String name) {
        List<Xman> xmanBs = getByName(name);
        List<Xman> partners = new ArrayList<Xman>();
        for (Xman xmanB : xmanBs)
            for(int i = 0; i < size; ++i){
                if(dnaSeq[i].size() == 0)continue;
                Xman xmanA = dnaSeq[i].get(0);
                if(xmanB.getEnemy().contains(xmanA.getDNASequence()))continue;
                boolean ok = true;
                for(int j = 0; j < xmanB.getEnemy().size(); ++j){
                    Xman enemy = getByDNASequence(xmanB.getEnemy().get(j));
                    if(!enemy.getEnemy().contains(xmanA.getDNASequence())){
                        ok = false;
                        break;
                    }
                }
                if(ok)
                    partners.add(xmanA);
            }

        return partners;
    }
    /**
     * 给定Xman的名字,找到他/她的主要对手。 当且仅当A在B的敌方列表中并且A在B的所有朋友的敌方列表
     * 中时,XmanA才是另一个XmanB的敌手。如果未找到任何敌方,则返回空列表。
     * 如果找到多个具有相同名称的Xman,则将其所有主要竞争对手串联在一起。
     * */
    public List<Xman> archrival(String name) {
        List<Xman> xmanBs = getByName(name);
        List<Xman> archrivals = new ArrayList<Xman>();
        for (Xman xmanB : xmanBs)
            for (int i = 0; i < size; ++i)
            {
                Xman xmanA = dnaSeq[i].get(0);
                if(xmanB.getEnemy().contains(xmanA.getDNASequence()))continue;
                boolean ok = true;
                List<Xman> Bfriends = friends(xmanB.getDNASequence());
                for(Xman bfriend : Bfriends)
                    if(!bfriend.getEnemy().contains(xmanA.getDNASequence())){
                        ok = false;
                        break;
                    }
                if(ok)
                    archrivals.add(xmanA);
            }
        return archrivals;
    }
}

猜你喜欢

转载自www.cnblogs.com/YY666/p/11778724.html