在对象构造期间向ArrayList添加元素的最佳实践?

时间:2014-03-22 22:45:32

标签: java arraylist

所以我正在为我的在线AP计算机科学课做一个项目并且遇到了一个问题...这是我给予构建的原始类定义(剥离了与我的问题无关的代码):

注意:Bin类的构造函数接受一个参数String。字符串代表Bin的名称。

import java.util.*;
public class Warehouse
{
    // Declare instance variables here

    public Warehouse( int binMax )
    {
        myBinMax = binMax;
        myCatalog = new ArrayList<MusicMedia>();
        myBins = new ArrayList<Bin>( 5 );
        // Code that will start the warehouse
        // off with 5 empty bins
    }

    public void addBin()
    {
        myBins.add( new Bin( "B" + myBins.size() ) );
    }
}

我的工作是用实际代码实现替换注释掉的区域。虽然实例变量的声明非常简单,但我更倾向于实现第二条评论中提到的代码的最佳方法。

简而言之,哪个是完成上述构造函数的最佳方法?

解决方案A:

private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;

public Warehouse( int binMax )
{
    myBinMax = binMax;
    myCatalog = new ArrayList<MusicMedia>();
    myBins = new ArrayList<Bin>( 5 );
    for(int i = 0; i < 5; i++)
    {
        myBins.add( new Bin( "B" + myBins.size() ) );
    }
}

解决方案B:

private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;

public Warehouse( int binMax )
{
    myBinMax = binMax;
    myCatalog = new ArrayList<MusicMedia>();
    myBins = new ArrayList<Bin>( 5 );
    for(int i = 0; i < 5; i++)
    {
        addBin(); // <= Is this considered bad practice?
    }
}

解决方案C:

// Some magical wizard code I would have never thought of. XD

提前致谢!

3 个答案:

答案 0 :(得分:2)

你能使用Java 8吗?

final List<Bin> bins = IntStream.range(0, 5).
        mapToObj(i -> new Bin("Bin" + i)).
        collect(Collectors.toCollection(ArrayList::new));

否则,您的解决方案看起来都很好。我希望B,因为您已经有一个addBin方法,但有一个警告。您必须addBin final,因为它是public方法。您应该只从构造函数中调用privatefinal方法,否则您可能会冒某人(可能是您)在子类中重写该方法,然后在初始化子类之前从超类构造函数调用子类方法。

答案 1 :(得分:1)

尝试在代码中使用常量而不是幻数:)

import java.util.*;
public class Warehouse
{
    // Declare instance variables here
        private static final int INITIAL_BINS = 5;
        private static final String DEFAULT_BINNAME = "DefaultBin_";

    public Warehouse( int binMax )
    {
        myBinMax = binMax;
        myCatalog = new ArrayList<MusicMedia>();
        myBins = new ArrayList<Bin>( INITIAL_BINS );
        for(int i = 0; i < INITIAL_BINS; i++)
        {
            myBins.add( new Bin( DEFAULT_BINNAME + i ) );
            //addBin();// This is fine too depends on how flexible you want naming to be:)
        }
    }

    public void addBin()
    {
        myBins.add( new Bin( "B" + myBins.size() ) );

    }
}

答案 2 :(得分:1)

虽然我同意大多数已经说过的内容,但java 8函数编程风格的单行程非常性感。应避免使用魔术数字/字符串。如果你的课程没有超越功能风格,为什么不将整个for循环移动到它自己的功能中呢?通常,构造函数应该做的唯一事情就是初始化对象的状态。为了明确这一点,我尝试保持每个成员变量一行,并且一行只不过是一个初始化语句。 IMO方法(可以引用对象的当前状态)不应该从构造函数中调用,因为您的对象尚未创建。如果要添加函数来帮助初始化对象,请随意执行此操作但保持静态,以便明确函数的意图(不是指对象的状态)。

...
private static final int INITIAL_BIN_COUNT = 5;
private static final String BIN_PREFIX = "B";
private final List<Bin> myBins;

public Warehouse(...) {
    ....
    myBins = initMyBins();
}

private static List<Bin> initMyBins() {
    final List<Bin> result = new ArrayList<Bin>(INITIAL_BIN_COUNT);
    for(int i = 0; i < INITIAL_BIN_COUNT; i++) {
        result.add(new Bin(BIN_PREFIX+i));
    }
    return result;
}
...

P.S。还有一些注意事项,通常很好的做法是编写接口类型而不是具体的类类型(可能你还没有覆盖接口,但这就是我将ArrayList更改为List所做的。 / p>