将数组与整数添加到ArrayList <integer>

时间:2018-03-12 23:47:58

标签: java arraylist

作为练习,我将7个整数(每个整数介于1和39之间)添加到ArrayList,然后使用for循环打印出整数。我似乎得到了预期的输出(例如,彩票号码:3 5 10 14 15 27 37)。但是我的代码没有通过自动化测试。该测试给出以下错误消息:“在drawNumbers调用之后,数字列表的大小应为7!预期:&lt; 7&gt;但是:&lt; 14&gt;”

我想也许我将7个整数添加为14个单独的数字而不是7个双位整数。但是,我对此非常不确定。能够深入了解出了什么问题会很棒。

主程序:

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        LotteryNumbers lotteryNumbers = new LotteryNumbers();
        ArrayList<Integer> numbers = lotteryNumbers.numbers();

        System.out.println("Lottery numbers:");
        for(int number : numbers) {
            System.out.print(number + " ");
        }
        System.out.println("");
    }
}

和班级:

import java.util.ArrayList;
import java.util.Random;

public class LotteryNumbers {
    private final ArrayList<Integer> numbers;
    private final Random random;
    private int number;

    public LotteryNumbers() {
        this.numbers = new ArrayList<Integer>();
        this.random = new Random();
        this.drawNumbers();
    }

    public ArrayList<Integer> numbers() {
        return this.numbers;
    }

    public void drawNumbers() {
        int i = 0;
        while(i < 7) {
            while(true) {
                this.number = random.nextInt(39)+1;
                if(!containsNumber(number)) {
                    break;
                }
            }
            this.numbers.add(this.number);
            i++;
        }
    }

    public boolean containsNumber(int number) {
        return numbers.contains(number);
    }

}

以下是测试代码:

import fi.helsinki.cs.tmc.edutestutils.Points;
import static org.junit.Assert.*;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

@Points("82")
public class LotteryNumbersTest {

    public ArrayList<Integer> test() {
        LotteryNumbers lottoRivi;
        ArrayList<Integer> numerot;

        try {
            lottoRivi = new LotteryNumbers();
            numerot = lottoRivi.numbers();
        } catch (Throwable t) {
            fail("Something went wrong when creating a new LotteryNumbers object! More info: " + t);
            return null; // tyhmä java
        }

        assertEquals("The size of number list should be seven!", 7, numerot.size());

        Set<Integer> jaljellaOlevatNumerot = new HashSet<Integer>();
        for (int i = 1; i <= 39; i++) {
            jaljellaOlevatNumerot.add(i);
        }

        Set<Integer> arvotutNumerot = new HashSet<Integer>();
        for (int i : numerot) {
            assertTrue("A lottery number should belong to range 1-39. However, you returned number: " + i,
                    (i >= 1 && i <= 39));
            assertTrue("The method containsNumber() returns false, despite the drawn number was among the list of drawn numbers: " + i,
                    lottoRivi.containsNumber(i));
            assertTrue("The numbers returned contain multiple times a number: " + i,
                    arvotutNumerot.add(i));
            jaljellaOlevatNumerot.remove(i);
        }

        for (int i : jaljellaOlevatNumerot) {
            assertFalse("The method containsNumber() returns true, despite the drawn number was not among the list of drawn numbers: " + i,
                    lottoRivi.containsNumber(i));
        }

        return numerot;
    }

    @Test
    public void testOne() {
        test();
    }

    @Test
    public void testDrawNumbersCallRemovesOldNumbersAndDrawsNew() {
        LotteryNumbers lottoRivi;
        ArrayList<Integer> numerot;
        try {
            lottoRivi = new LotteryNumbers();
            numerot = lottoRivi.numbers();
        } catch (Throwable t) {
            fail("Something went wrong when creating a new LotteryNumbers object! More info: " + t);
            return;
        }
        String numerotString = numerot.toString();
        assertEquals("The size of number list should be seven!", 7, numerot.size());
        lottoRivi.drawNumbers();
        assertEquals("The size of number list should be seven after drawNumbers call!", 7, lottoRivi.numbers().size());
        assertFalse("New numbers should have been drawn with drawNumbers call! Numbers were " + numerotString,numerotString.equals(lottoRivi.numbers().toString()));
    }

    @Test
    public void testMany() {
        int[] arr = new int[40];
        for (int i = 0; i < 200; i++) {
            for (int x : test()) {
                arr[x]++;
            }
        }

        int montako=0;
        for (int i = 1; i <= 39; i++) {
            if (arr[i]>0) {
                montako++;
            }
        }

        assertEquals("200 lottery draws produced only " + montako +
                " different values! Not very random!", 39, montako);
    }
}

实现了@Eran的建议,将numbers.clear()作为drawNumbers()方法的第一个语句,代码给出了正确的输出并通过了测试。这使我能够将我的代码提交给课程提供者(TestMyCode MOOC),然后查看我在下面粘贴的模型答案:

import java.util.ArrayList;
import java.util.Random;

public class LotteryNumbers {
    private ArrayList<Integer> numbers;

    public LotteryNumbers() {
        // Draw numbers as LotteryNumbers is created
        this.drawNumbers();
    }

    public ArrayList<Integer> numbers() {
        return this.numbers;
    }

    public void drawNumbers() {
        // We'll format a list for the numbers
        this.numbers = new ArrayList<Integer>();
        // Write the number drawing here using the method containsNumber()
        Random random = new Random();
        while (this.numbers.size() < 7) {
            int newNumber = random.nextInt(39) + 1;
            boolean alreadyDrawn = this.containsNumber(newNumber);

            // we add the number only if it is not already among the drawn numbers
            if (!alreadyDrawn) {
                this.numbers.add(newNumber);
            }
        }
    }

    public boolean containsNumber(int number) {
        // Test here if the number is already in the drawn numbers
        for (int n : this.numbers) {
            if (n == number) {
                return true;
            }
        }
        return false;
    }
}

4 个答案:

答案 0 :(得分:3)

您正在drawNumbers()构造函数中调用LotteryNumbers,因此在创建LotteryNumbers实例后,它已包含7个数字。

根据自动化测试的消息 - The size of number list should be seven after drawNumbers call! expected:<7> but was:<14> - 它可能会再次调用drawNumbers(),这会在列表中再添加7个数字。因此,您最终得到14个数字。

您应该从构造函数中删除对drawNumbers()的调用。

编辑:

看到测试方法 - testDrawNumbersCallRemovesOldNumbersAndDrawsNew() - 您后来添加到问题中,它希望列表在调用drawNumbers()之前和之后有7个数字。因此,您应该在构造函数中保留drawNumbers(),但要清除drawNumbers()开头的列表(通过调用numbers.clear())。

答案 1 :(得分:3)

这种情况下的修复很简单,只需在clear()开头的ArrayList上调用drawNumbers()

public void drawNumbers() {
    numbers.clear();
    int i = 0;
    while(i < 7) {
        while(true) {
            this.number = random.nextInt(39)+1;
            if(!containsNumber(number)) {
                break;
            }
        }
        this.numbers.add(this.number);
        i++;
    }
}

此外,您应该考虑仅提供ArrayList的副本,因此对ArrayList的修改不会反映在您的类中,反之亦然。

答案 2 :(得分:2)

正如Eran所说,问题可能是测试用例明确调用了drawNumbers(),从而在numbers列表中添加了7个元素。

考虑什么&#34; drawNumbers&#34;应该这样做:它应该添加更多数字,还是应该随机抽取替换数字?

由于您没有清除数字列表,如果我drawNumbers()被调用5次,代码将进入无限循环!

答案 3 :(得分:1)

绝对不要将整数作为单个数字添加。

在这种情况下,drawNumbers()方法执行两次。你在构造函数中调用它,然后它会在测试用例中调用一次,这就是为什么计数为14。

在构造函数中注释drawNumbers()并将其添加到main方法

public LotteryNumbers() {
    this.numbers = new ArrayList<Integer>();
    this.random = new Random();
    //this.drawNumbers();
}

public static void main(String[] args) {
    LotteryNumbers lotteryNumbers = new LotteryNumbers();
    lotteryNumbers.drawNumbers();
    ArrayList<Integer> numbers = lotteryNumbers.numbers();

    System.out.println("Lottery numbers:");
    for(int number : numbers) {
        System.out.print(number + " ");
    }
    System.out.println(numbers.size());
}

编辑:看到测试用例后,上面的答案是错误的。您必须将clear()添加到上面其他人提到的方法