简体   繁体   English

将候选对象的数组列表与从文本文件读取的数据进行比较

[英]Comparing an arraylist of Candidate objects to data read from a text file

First and foremost this is an assignment for my college class. 首先,这是我大学课程的作业。 Please do not hack the answer out for me as it will not help me help myself. 请不要为我破解答案,因为它不会帮助我自助。 I'm merely looking for an experienced point of view as to why I have hit a brick wall on something that seems easy. 我只是在寻找有经验的观点,说明为什么我在看起来很简单的东西上碰壁。

What I have done: I have an Election class that will add Candidate objects to an ArrayList of type Candidate. 我做了什么:我有一个Election类,它将把Candidate对象添加到Candidate类型的ArrayList中。 A Candidate object has the following attributes, a name, id, and total number of votes (that starts at zero, of course). 候选对象具有以下属性,名称,标识和投票总数(当然,从零开始)。 These Candidate objects are created and stored into an Candidate[] within the main client. 这些候选对象被创建并存储到主客户端中的Candidate []中。 The Candidate object's are then added to the Arraylist of type Candidate - located in the Election class. 然后将候选对象的对象添加到位于Election类中的Candidate类型的Arraylist中。

My Problem: The votes for a Candidate are read from a text file that consists of numbers 1 -24. 我的问题:从包含数字1 -24的文本文件中读取候选人的票数。 Each vote corresponds to the id of a Candidate. 每个投票对应一个候选人的ID。 In the countVotes method located in the Election class I'm reading the text file containing the votes. 在Election类中的countVotes方法中,我正在读取包含投票的文本文件。 I am then trying to compare the votes read from the text file in real-time to a Candidate's id. 然后,我尝试将实时从文本文件读取的投票与候选人的ID进行比较。 If a vote and Id are equal then increment count to get total number of votes for a Candidate. 如果投票和Id相等,则递增计数以获得候选人的投票总数。 However, this method will only work for one Candidate id at a time. 但是,此方法一次仅适用于一个候选人ID。 For example if I fed the method call countVotes(readFile, cands[1]) it will work for only the specific Candidate. 例如,如果我输入方法调用countVotes(readFile,cands [1]),它将仅适用于特定的候选对象。 I know that I should probably store the votes in another ArrayList and then do comparison using two ArrayLists. 我知道我应该将选票存储在另一个ArrayList中,然后使用两个ArrayList进行比较。 I'm looking for insight on how to go about comparing the votes read from the text file to each Candidate's id and then setting the total number of votes counted for each Candidate. 我正在寻找有关如何比较从文本文件读取的投票和每个候选人的ID,然后设置为每个候选人计算的总票数的见解。

Here is the Candidate class: 这是候选人类别:

package problem_one;

public class Candidate <E> {
    protected String name;
    protected int id;
    protected int votes;

    public Candidate(String name, int id){
        this.name = name;
        this.id = id;
        votes = 0;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void setVotes(int votes) {
        this.votes = votes;
    }

    public int getVotes(){
        return votes;
    }

    public String toString(){
        String display = "\nCandidate: " + getName() + "\nID: " + getId() + "\nVotes: " + getVotes() + "\n";

        return display;
    }
}

Here is the Election Class: 这是选举班:

package problem_one;

import java.util.ArrayList;
import java.util.Scanner;

public class Election<E>{

    @SuppressWarnings("rawtypes")
    protected ArrayList<Candidate> ballot = new ArrayList<Candidate>();

    public void addCandidate(Candidate<E> cand){
        ballot.add(cand);
    }

    public void countVotes(Scanner readFile, Candidate cand){

        Integer vote;
        int count = 0;

            while(readFile.hasNextInt()){
                vote = readFile.nextInt();

                if(vote.equals(cand.getId())){
                    count++;
                    cand.setVotes(count);
                }
            }
    }

    public String toString(){
        String display = "";

        for(Candidate cand : ballot){
            display += cand;
        }
        return display;
    }
}

Here is the main client: 这是主要客户:

package pa2_clients;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

import problem_one.Candidate;
import problem_one.Election;

public class problem_one_client {

    public static void main(String[] args) {
        Election<Object> elect = new Election<Object>();
        File file = new File("votes");
        Scanner readFile;

        Candidate[] cands = new Candidate[24];

        cands[0] = new Candidate<Object>("Washingtion", 1);
        cands[1] = new Candidate<Object>("Adams", 2);
        cands[2] = new Candidate<Object>("Jefferson", 3);
        cands[3] = new Candidate<Object>("Madison", 4);
        cands[4] = new Candidate<Object>("Monroe", 5);
        cands[5] = new Candidate<Object>("Quincy Adams", 6);
        cands[6] = new Candidate<Object>("Jackson", 7);
        cands[7] = new Candidate<Object>("Van Buren", 8);
        cands[8] = new Candidate<Object>("Harrision", 9);
        cands[9] = new Candidate<Object>("Tyler", 10);
        cands[10] = new Candidate<Object>("Polk", 11);
        cands[11] = new Candidate<Object>("Taylor", 12);
        cands[12] = new Candidate<Object>("Fillmore", 13);
        cands[13] = new Candidate<Object>("Pierce", 14);
        cands[14] = new Candidate<Object>("Buchanan", 15);
        cands[15] = new Candidate<Object>("Lincoln", 16);
        cands[16] = new Candidate<Object>("Johnson", 17);
        cands[17] = new Candidate<Object>("Grant", 18);
        cands[18] = new Candidate<Object>("Hayes", 19);
        cands[19] = new Candidate<Object>("Garfield", 20);
        cands[20] = new Candidate<Object>("Arthur", 21);
        cands[21] = new Candidate<Object>("Cleveland", 22);
        cands[22] = new Candidate<Object>("McKinely", 23);
        cands[23] = new Candidate<Object>("Roosevely", 24);

        for(Candidate cand : cands){
            elect.addCandidate(cand);

        }

        try {
            readFile = new Scanner(file);

            elect.countVotes(readFile, cands[0]);

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(elect.toString());
    }

}

The output from running the program: 运行程序的输出:

Candidate: Washingtion
ID: 1
Votes: 1669

Candidate: Adams
ID: 2
Votes: 0

Candidate: Jefferson
ID: 3
Votes: 0

Candidate: Madison
ID: 4
Votes: 0

Candidate: Monroe
ID: 5
Votes: 0

Candidate: Quincy Adams
ID: 6
Votes: 0

Candidate: Jackson
ID: 7
Votes: 0

Candidate: Van Buren
ID: 8
Votes: 0

Candidate: Harrision
ID: 9
Votes: 0

Candidate: Tyler
ID: 10
Votes: 0

Candidate: Polk
ID: 11
Votes: 0

Candidate: Taylor
ID: 12
Votes: 0

Candidate: Fillmore
ID: 13
Votes: 0

Candidate: Pierce
ID: 14
Votes: 0

Candidate: Buchanan
ID: 15
Votes: 0

Candidate: Lincoln
ID: 16
Votes: 0

Candidate: Johnson
ID: 17
Votes: 0

Candidate: Grant
ID: 18
Votes: 0

Candidate: Hayes
ID: 19
Votes: 0

Candidate: Garfield
ID: 20
Votes: 0

Candidate: Arthur
ID: 21
Votes: 0

Candidate: Cleveland
ID: 22
Votes: 0

Candidate: McKinely
ID: 23
Votes: 0

Candidate: Roosevely
ID: 24
Votes: 0

EDIT: 编辑:

Thank you Adriaan for your advice and time. 感谢Adriaan的建议和时间。

I was able to fix the problem by implementing another ArrayList to hold the votes read from the txt file. 我能够通过实现另一个ArrayList来保存从txt文件读取的投票来解决该问题。 Furthermore, I now understand that using a Map as the data structure to hold the Candidate objects would be the better option. 此外,我现在知道,使用Map作为数据结构来保存候选对象将是更好的选择。

The reason I decided to stay with my implementation is because I now have to implement a priority queue and I'm not sure how to use a Map with a priority queue. 我决定继续执行的原因是因为我现在必须实现优先级队列,并且不确定如何将Map与优先级队列一起使用。 Otherwise, thank you again for the knowledge you have passed my way. 否则,再次感谢您了解我的知识。 Posting the updated code... Please feel free to comment on the updated solution. 正在发布更新的代码...请随时评论更新的解决方案。

Updated Candidate Class: 更新的候选类别:

package problem_one;

public class Candidate {

    private String name;
    private int id;
    private int votes;

    public Candidate(String name, int id) {
        this.name = name;
        this.id = id;
        votes = 0;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void addVote() {
        votes++;
    }

    public int getVotes() {
        return votes;
    }

    public String toString() {
        StringBuilder str = new StringBuilder();

        str.append("\nCandidate: " + getName());
        str.append("\nID: " + getId());
        str.append("\nVotes: " + getVotes() + "\n");

        return str.toString();
    }
}

The Updated Election Class: 更新的选举班:

package problem_one;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Election {

    private List<Candidate> ballot = new ArrayList<Candidate>();
    private List<Integer> votes = new ArrayList<Integer>();

    public void addCandidate(Candidate cand) {
        ballot.add(cand);
    }

    public void readVotes(Scanner readFile) {
        int vote;

        while (readFile.hasNextInt()) {
            vote = readFile.nextInt();
            votes.add(vote);
        }
    }

    public void countVotes(Candidate cand) {
        for (int i = 1; i < votes.size(); i++) {
            if (votes.get(i).equals(cand.getId())) {
                cand.addVote();
            }
        }
    }

    public String toString() {
        StringBuilder str = new StringBuilder();

        for (Candidate cand : ballot) {
            str.append(cand);
        }
        return str.toString();
    }
}

The output: 输出:

Candidate: Washington
ID: 1
Votes: 1669

Candidate: Adams
ID: 2
Votes: 1495

Candidate: Jefferson
ID: 3
Votes: 103

Candidate: Madison
ID: 4
Votes: 32

Candidate: Monroe
ID: 5
Votes: 1474

Candidate: Quincy Adams
ID: 6
Votes: 1653

Candidate: Jackson
ID: 7
Votes: 44

Candidate: Van Buren
ID: 8
Votes: 2730

Candidate: Harrision
ID: 9
Votes: 112

Candidate: Tyler
ID: 10
Votes: 808

Candidate: Polk
ID: 11
Votes: 327

Candidate: Taylor
ID: 12
Votes: 33

Candidate: Fillmore
ID: 13
Votes: 1037

Candidate: Pierce
ID: 14
Votes: 41

Candidate: Buchanan
ID: 15
Votes: 313

Candidate: Lincoln
ID: 16
Votes: 1438

Candidate: Johnson
ID: 17
Votes: 428

Candidate: Grant
ID: 18
Votes: 1346

Candidate: Hayes
ID: 19
Votes: 1512

Candidate: Garfield
ID: 20
Votes: 1171

Candidate: Arthur
ID: 21
Votes: 539

Candidate: Cleveland
ID: 22
Votes: 132

Candidate: McKinely
ID: 23
Votes: 304

Candidate: Roosevelt
ID: 24
Votes: 33

EDIT FINAL SOLUTION: 编辑最终解决方案:

Here is the final solution that I turned in... I didn't get to rework the code completely due to having other assignments to finish. 这是我上交的最终解决方案...由于要完成其他任务,所以我无法完全重新编写代码。

The comparator had to be implemented inside the for loop located in the Election class method startElectionProblemTwo. 比较器必须在Election类方法startElectionProblemTwo中的for循环内实现。 This was the only way I could get the comparator to produce the expected results. 这是我可以使比较器产生预期结果的唯一方法。 This happened because I didn't plan for changing the code down the road. 发生这种情况是因为我不打算在将来更改代码。 Which is something I should have done from the beginning. 我应该从一开始就要做。

Also I wanted to read in the Candidates from a file but didn't get to implement this before the due date. 我也想从文件中读取候选人,但没有在截止日期之前实现。

The comparator is used when the votes are equal. 票数相等时使用比较器。 When the votes are equal we then check the number of consecutive terms served. 当票数相等时,我们将检查连续任期的数目。 Less terms served win, if the terms served are equal then we compare by name. 送达的条款较少,如果送达的条款相等,则按名称进行比较。

Candidate class: 候选人类别:

package problem_one;

public class Candidate {

    private String name;
    private int id;
    private int votes;
    private int terms;

    public Candidate(String name, int id, int terms){
        this.name = name;
        this.id = id;
        this.terms = terms;
        votes = 0;
    }

    public Candidate(){

    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void addVote() {
        votes++;
    }

    public int getVotes() {
        return votes;
    }

    public int getTerms() {
        return terms;
    }

    public String toString() {
        StringBuilder str = new StringBuilder();

        str.append("Candidate: " + getName());
        str.append("\nID: " + getId());
        str.append("\nTerms: " + getTerms());
        str.append("\nVotes: " + getVotes() + "\n");

        return str.toString();
    }
}

Election class: 选举班:

package problem_one;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

import problem_two.ElectionTieBreaker;

public class Election extends Candidate{

    // Priority Queue using a max heap.
    private List<Candidate> ballotPq;

    // Stores the votes read from the *votes* file.
    private List<Integer> votes = new ArrayList<Integer>();

    public Election(String name, int id, int terms){
        super(name, id, terms);
    }

    public Election(){
        ballotPq = new ArrayList<Candidate>();
    }

    // Change to PQ offer method.
    public void offer(Candidate cand) {
        countVotes(cand);
        ballotPq.add(cand);

        int child = ballotPq.size() - 1;
        int parent = ((child - 1) / 2);

        while (parent >= 0 && ballotPq.get(parent).getVotes() < ballotPq.get(child).getVotes()) {
            swap(parent, child);
            child = parent;
            parent = ((child - 1) / 2);
        }
    }

    // Modified Priority Queue method poll.
    private Candidate poll() {

        // Return null if the ArrayList is empty.
        if (isEmpty())
            return null;

        // Sets cand to the Candidate object at index 0.
        Candidate cand = ballotPq.get(0);

        // Check if there is only one Candidate object.
        if (ballotPq.size() == 1) {
            ballotPq.remove(0);
            return cand;
        }

        // Move the last element to the head of the Priority Queue.
        ballotPq.set(0, ballotPq.remove(ballotPq.size() - 1));
        int parent = 0;

        while (true) {

            // Finds the parents left-child, i.e. Parents left child is at 2i + 1.
            int leftChild = ((2 * parent) + 1);

            // Break out of loop.
            if (leftChild >= ballotPq.size()) {
                break;
            }

            // Finds the parents right-child, i.e. Parents right child is at 2i + 2.
            int rightChild = (leftChild + 1);

            // Assert that the leftChild is the min child 
            int minChild = leftChild;

            // If true sets the min child
            if (rightChild < ballotPq.size() && ballotPq.get(leftChild).getVotes() < ballotPq.get(rightChild).getVotes()) {
                minChild = rightChild;

            }
            //  Swaps the parent and min child if true
            if (ballotPq.get(parent).getVotes() < ballotPq.get(minChild).getVotes()) {
                swap(parent, minChild);
                parent = minChild;

            } else {break;}
        }
        return cand;
    }

    // Checks if the ArrayList is empty.
    private boolean isEmpty() {
        return ballotPq.size() == 0;
    }

    // Swaps the parent and child at the specified indices.
    private void swap(int i, int j) {
        Candidate one = ballotPq.get(i);
        Candidate two = ballotPq.get(j);

        ballotPq.set(i, two);
        ballotPq.set(j, one);
    }

    // Reads the votes from the *votes* txt file.
    private void readVotes() {
        File file = new File("votes");
        Scanner readFile;

        try {
            readFile = new Scanner(file);

            while (readFile.hasNextInt()) {
                int vote = readFile.nextInt();
                votes.add(vote);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    // Counts the total votes casted for each Candidate.
    private void countVotes(Candidate cand) {
        for (int i = 0; i < votes.size(); i++) {
            if (votes.get(i).equals(cand.getId())) {
                cand.addVote();
            }
        }
    }

    // Starts the election for problem one
    public void startElectionProblemOne() {
        readVotes();

        offer(new Candidate("Washington", 1, 3));
        offer(new Candidate("Adams", 2, 3));
        offer(new Candidate("Jefferson", 3, 2));
        offer(new Candidate("Madison", 4, 2));
        offer(new Candidate("Monroe", 5, 2));
        offer(new Candidate("Quincy Adams", 6, 1));
        offer(new Candidate("Jackson", 7, 1));
        offer(new Candidate("Van Buren", 8, 3));
        offer(new Candidate("Harrision", 9, 1));
        offer(new Candidate("Tyler", 10, 2));
        offer(new Candidate("Polk", 11, 2));
        offer(new Candidate("Taylor", 12, 3));
        offer(new Candidate("Fillmore", 13, 2));
        offer(new Candidate("Pierce", 14, 2));
        offer(new Candidate("Buchanan", 15, 1));
        offer(new Candidate("Lincoln", 16, 1));
        offer(new Candidate("Johnson", 17, 2));
        offer(new Candidate("Grant", 18, 3));
        offer(new Candidate("Hayes", 19, 2));
        offer(new Candidate("Garfield", 20, 1));
        offer(new Candidate("Arthur", 21, 1));
        offer(new Candidate("Cleveland", 22, 4));
        offer(new Candidate("McKinely", 23, 1));
        offer(new Candidate("Roosevelt", 24, 3));

        System.out.println("Elected City Supervisor " + "\n" + poll());

        for (int i = 0; i < 4; i++) {
            System.out.println("Elected City Council " + "\n" + poll());
        }
    }

    // Starts the election for problem two
    public void startElectionProblemTwo(){
        readVotes();

        offer(new Candidate("Washington", 1, 3));
        offer(new Candidate("Adams", 2, 3));
        offer(new Candidate("Jefferson", 3, 2));
        offer(new Candidate("Madison", 4, 2));
        offer(new Candidate("Monroe", 5, 2));
        offer(new Candidate("Quincy Adams", 6, 1));
        offer(new Candidate("Jackson", 7, 1));
        offer(new Candidate("Van Buren", 8, 3));
        offer(new Candidate("Harrision", 9, 1));
        offer(new Candidate("Tyler", 10, 2));
        offer(new Candidate("Polk", 11, 2));
        offer(new Candidate("Taylor", 12, 3));
        offer(new Candidate("Fillmore", 13, 2));
        offer(new Candidate("Pierce", 14, 2));
        offer(new Candidate("Buchanan", 15, 1));
        offer(new Candidate("Lincoln", 16, 1));
        offer(new Candidate("Johnson", 17, 2));
        offer(new Candidate("Grant", 18, 3));
        offer(new Candidate("Hayes", 19, 2));
        offer(new Candidate("Garfield", 20, 1));
        offer(new Candidate("Arthur", 21, 1));
        offer(new Candidate("Cleveland", 22, 4));
        offer(new Candidate("McKinely", 23, 1));
        offer(new Candidate("Roosevelt", 24, 3));

        for (int i = 0; i < 24; i++) {
            // Comparator for candidates
            Collections.sort(ballotPq, new ElectionTieBreaker());
            System.out.println(poll());
        }
    }
}

ElectionTieBreaker class: ElectionTieBreaker类别:

package problem_two;

import java.util.Comparator;

import problem_one.Candidate;

public class ElectionTieBreaker implements Comparator<Candidate> {

    @Override
    public int compare(Candidate o1, Candidate o2) {
        int flag = o2.getVotes() - o1.getVotes();

        // if the votes are the same 
        if(flag != 0){
            return flag;
        }
        if(o1.getTerms() - o2.getTerms() == 0){
            flag = o1.getName().compareTo(o2.getName());
        }else{
            flag = o1.getTerms() - o2.getTerms();
        }
        return flag;
    }
}

ProblemOneClient: ProblemOneClient:

package pa2_clients;

import problem_one.Election;

public class ProblemOneClient {

    public static void main(String[] args) {
        Election election = new Election();
        election.startElectionProblemOne();
    }

}

ProblemTwoClient: ProblemTwoClient:

package pa2_clients;

import problem_one.Election;

public class ProblemTwoClient {

    public static void main(String[] args) {
        Election elect = new Election();
        elect.startElectionProblemTwo();
    }
}

Normally you should declare fields as private (not protected or default). 通常,您应将字段声明为私有字段(不受保护或默认)。

Also declare fields by their interface, not their implementation, so: 还通过其接口而不是其实现声明字段,因此:

private List<Candidate> ballot = new ArrayList<Candidate>();

You have a typo in the name of your first and ninth candidates. 您的第一个和第九个候选人的名字有错字。

Your main class has a non-standard name, change it for example to ProblemOneClient . 您的主类具有非标准名称,例如将其更改为ProblemOneClient

You have added generic class types to Candidate and Election which you are not using and don't need - remove them (the generic types, not the classes). 您已将不使用且不需要的通用类类型添加到“ Candidate和“ Election中-删除它们(通用类型,而不是类)。 This will also get rid of the SuppressWarnings annotation. 这也将摆脱SuppressWarnings注释。

In your main method you are first creating an array of Candidates and then iterating over them to put them in an ArrayList. 在您的主要方法中,您首先要创建一个候选数组,然后对其进行迭代以将它们放入ArrayList中。 You don't need the array. 您不需要数组。

How about using a java.util.Map ? 如何使用java.util.Map呢? You could store a candidate in it like this: 您可以像这样在其中存储候选人:

Map<Integer, Candidate> candidates = new HashMap<Integer, Candidate>();
Candidate candidate = new Candidate<Object>("Van Buren", 8);
candidates.put(candidate.getId(), candidate);

And then find the candidate by id like this: 然后像这样通过id查找候选人:

Integer vote = 8;
Candidate candidate = candidates.get(vote);

EDIT: some more hints 编辑:更多提示

I propose changing the API of Candidate : 我建议更改Candidate的API:

public void addVote() {
    votes++;
}

public int getVotes() {
    return votes;
}

Inc-ing the number of votes is more convenient (and avoids fraud). 增加票数会更方便(并避免欺诈)。

In your Election.toString() you should use StringBuilder instead of String concatenation to avoid the memory usage caused by all the intermediate Strings being interned in the String pool . Election.toString() ,应使用StringBuilder而不是String串联,以避免由所有中间String插入到String pool中引起的内存使用。

You could consider adding the candidates to a List there and sort them descending by their number of votes: 您可以考虑将候选者添加到该列表中,然后按投票数的降序对它们进行排序:

    List<Candidate> rank = new ArrayList<Candidate>(ballot.values());
    Collections.sort(rank, new Comparator<Candidate>() {
        @Override
        public int compare(Candidate o1, Candidate o2) {
            return o2.getVotes() - o1.getVotes();
        }
    });

Of course this will get done each time toString() is called so maybe a separate method would be better ( toString() is normally not supposed to do a lot of work). 当然,每次调用toString()都会完成此操作,因此也许有一个单独的方法会更好(通常不建议toString()做很多工作)。 For example you could move this into the method String Election.reportResults() . 例如,您可以将其移至String Election.reportResults()方法中。

Your main method could look like this, for improved readability: 您的主要方法可能如下所示,以提高可读性:

public static void main(String[] args) {
    Election election = new Election();

    addCandidates(election);

    countVotesFromFile(election, new File("votes"));

    System.out.println(election.reportResults());
}

Of course you still need to implement the methods addCandidates and countVotesFromFile . 当然,您仍然需要实现addCandidatescountVotesFromFile方法。

EDIT: You are currently passing the Scanner to your Election . 编辑:您当前正在将Scanner传递给您的Election This makes Election aware of (and thus dependent on) the use of Scanner . 这使Election意识到(并因此而依赖) Scanner的使用。 It is better design to hide this implementation detail in a single class and not share it (in this case between ProblemOneClient and Election ). 最好将设计细节隐藏在单个类中而不共享(在本例中,在ProblemOneClientElection之间)。

You also have a private List<Integer> votes in Election . 您还可以在Election获得private List<Integer> votes I think that is not elegant; 我认为这并不优雅; there is no need for Election to hold on to the complete list of votes. Election无需保留完整的选票清单。

One way of solving is to leave the iteration over votes in the ProblemOneClient and call Election.addVote(Integer) for each vote. 解决的一种方法是将迭代保留在ProblemOneClient中的ProblemOneClient并为每个表决调用Election.addVote(Integer) I like this because it is simple (it is suggested by the main method I provided above). 我喜欢它,因为它很简单(上面我提供的main方法建议这样做)。

An alternative approach is to write an implementation of Iterator<Integer> which you pass as argument to Election.addVotes(Iterator<Integer>) . 另一种方法是编写Iterator<Integer>的实现,将其作为参数传递给Election.addVotes(Iterator<Integer>) For a discussion of this exact issue, see here . 有关此确切问题的讨论,请参见此处

I made a comment about using StringBuilder your Election.toString() implementation and I noticed you also applied StringBuilder in Candidate.toString() . 我对在Election.toString()实现中使用StringBuilder进行了评论,并且注意到您还在Candidate.toString()应用了StringBuilder。 However in that case there is no iteration going on so you can simply format the result directly like so: 但是,在这种情况下,不会进行迭代,因此您可以像下面这样直接直接格式化结果:

public String toString() {
    return String.format("Candidate: %s, ID: %s, Votes: %s%n", name, id, votes);
}

I put the output on a single line to make it more compact. 我将输出放在一行上以使其更紧凑。 The %s placeholder is replaced by the String representation of the matching argument. %s占位符由匹配参数的字符串表示形式代替。 %n inserts a platform-specific newline. %n插入特定于平台的换行符。

EDIT: unit testing 编辑:单元测试

If you are interested I have an additional assignment for you, which is to write a unit test for the Election class. 如果您有兴趣,我还有另外一项任务,就是为Election类编写一个单元测试。 You can do that using the JUnit framework. 您可以使用JUnit框架来实现。

If you are using Maven to build your project, add this dependency to your pom.xml: 如果您使用Maven构建项目,则将此依赖项添加到pom.xml中:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>

If not, add this jar file to your classpath. 如果不是,请将此jar文件添加到您的类路径中。

A unit test typically resides in a separate source directory src/test/java/ . 单元测试通常位于单独的源目录src/test/java/ You can run it using Maven (eg mvn test on the command line) or within your IDE (eg 'run as test'). 您可以使用Maven(例如,命令行上的mvn test )或在您的IDE中(例如,“以测试方式运行”)运行它。

Here is a partially implemented unit test for Election : 这是Election的部分实施的单元测试:

import static org.junit.Assert.*;
// and some other imports 

public class ElectionTest {

    private Election instance;

    @Before
    public setUp() {
        instance = new Election();
    }

    @Test
    public void testAddCandidate() {
        // SETUP
        Candidate candidate = new Candidate("test", 42);

        // CALL
        instance.addCandidate(candidate);

        // VERIFY
        assertTrue(instance.reportResults().contains(candidate.toString()));
    }

    @Test
    public void testReadVotes() {
        fail("Not implemented yet");
    }

    @Test
    public void testCountVotes() {
        fail("Not implemented yet");
    }

    @Test
    public void testToString() {
        fail("Not implemented yet");
    }

    @Test
    public void testReadVotes() {
        fail("Not implemented yet");
    }
}

It is considered good practice to write unit tests for all your classes although some are more suitable for it than others. 为所有类编写单元测试被认为是一种好习惯,尽管有些比其他类更适合。 For example the ProblemOneClient is currently not easily unit-tested because it accesses a file directly. 例如, ProblemOneClient当前不容易进行单元测试,因为它直接访问文件。 The Candidate class can easily be tested but does not contain much interesting behavior to test (only the toString method actually). Candidate类可以轻松地进行测试,但是不包含很多有趣的行为来进行测试(实际上只是toString方法)。 Such a class is often called a model class. 这种类通常称为模型类。 I personally don't prefer to write unit tests for model classes; 我个人不喜欢为模型类编写单元测试。 they should be covered as part of other unit tests (they are often passed along as arguments, as also in this case). 它们应作为其他单元测试的一部分涵盖(它们通常作为参数传递,在这种情况下也是如此)。

Writing tests forces you to consider your design, easily testable classes are usually also more elegant. 编写测试会迫使您考虑设计,易于测试的类通常也更优雅。

Your issue is with this line in the main client. 您的问题是主要客户中的这一行。

elect.countVotes(readFile, cands[0]);

What that line is saying is that you want to apply all votes to the candidate in slot 0. 该行的意思是您想将所有选票应用于插槽0中的候选人。

Given the intent, the method signature for countVotes() may need to change. 给定意图,可能需要更改countVotes()的方法签名。

As an aside, consider using a Map, http://docs.oracle.com/javase/7/docs/api/java/util/Map.html , to store the candidates instead of an ArrayList. 顺便说一句,请考虑使用地图http://docs.oracle.com/javase/7/docs/api/java/util/Map.html来存储候选对象而不是ArrayList。

Best of luck! 祝你好运!

Comments on your final solution: 关于您最终解决方案的评论:

I would make the name and id fields final since they should never change. 我将使nameid字段成为最终字段,因为它们永远都不会更改。 You don't have to set votes to 0, this is the default for int fields. 您不必将votes设置为0,这是int字段的默认设置。 You can probably remove the default constructor, Election should definitely not extend Candidate ! 您可能可以删除默认构造函数, Election绝对不应扩展Candidate You could use a separate constructor for the final fields and a full constructor for convenience, but that's not really necessary. 您可以为最终字段使用单独的构造函数,为方便起见可以使用完整的构造函数,但这并不是必需的。 It just demonstrates you know about constructor chaining (-: 它只是说明您了解构造函数链接(-:

private final int id;
private final String name;

private int votes;
private int terms;

 public Candidate(int id, String name) {
    this.id = id;
    this.name = name;
}

public Candidate(int id, String name, int terms) {
    this(id, name);
    this.terms = terms;
}

As I mentioned the toString method can be replaced with: 正如我提到的,toString方法可以替换为:

public String toString() {
    return String.format("Candidate: %s%nID: %s%nTerms: %s%nVotes: %s%n", name, id, terms, votes);
}

I'm afraid the Election class has become a bit of a mess. 恐怕Election班变得一团糟。

Why on earth does Election extend Candidate? 为什么选举会扩展候选人呢?

You were apparently asked to implement a priority queue with a max heap implementation. 显然要求您使用最大堆实现来实现优先级队列。 It would have been better to create the PQ implementation in a separate class and have the Election class use it, instead of merging the PQ into Election . 最好在单独的类中创建PQ实现,并让Election类使用它,而不是将PQ合并到Election BTW this PQ implementation is a very good class to write a unit test for. 顺便说一句,此PQ实现是编写单元测试的很好的类。

The methods startElectionProblemOne and startElectionProblemTwo contain the same chunk of code where candidates are created. 方法startElectionProblemOnestartElectionProblemTwo包含创建候选者的相同代码块。 This should be extracted into a single method called from both to avoid duplication. 应该将其提取到从两者调用的单个方法中,以避免重复。

Why is countVotes called every time offer() is called? 为什么countVotes调用offer()都调用countVotes Counting votes is not related to the offer operation of your PQ. 计票与您的PQ的报价操作无关。

Your poll() method contains while (true) . 您的poll()方法包含while (true) In general this is a bad idea because it will be an endless loop if your logic within does not break as expected, and also not necessary. 通常,这是个坏主意,因为如果其中的逻辑没有按预期中断,并且也没有必要,它将是一个无限循环。 There must be some constraint on the parent variable you can test for in the loop condition... 您可以在循环条件下测试的parent变量上必须有一些约束...

I think readVotes() does not belong in the Election class. 我认为readVotes()不属于Election类。 It should not matter to the Election class if data is read from a file, database, service or is hard coded. 是从文件,数据库,服务中读取数据还是对其进行硬编码,对于Election类来说无关紧要。 In fact it should be agnostic of this (information hiding). 实际上,它应该是不可知的(信息隐藏)。 In a good design each class has a single responsibility. 在一个好的设计中,每个班级都有一个责任。

When the ElectionTieBreaker encounters two candidates with equal votes and terms it is ordering by name. ElectionTieBreaker遇到两个具有相同票数和条件的候选人时,它是按名称排序的。 I think this is wrong, in this case an error should be handled because it cannot be determined which candidate won. 我认为这是错误的,在这种情况下应该处理错误,因为无法确定哪个候选人获胜。 Simply letting the candidate with the name which comes first lexicographically is not fair! 简单地让候选人的名字按字典顺序排列是不公平的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM