【问题标题】:Store objects of different types in an ArrayList在 ArrayList 中存储不同类型的对象
【发布时间】:2020-05-05 21:36:13
【问题描述】:

我的应用程序从 csv 文件中读取数据并将其存储在对象中。我的 Load 类为此具有“load”方法,它读取 csv 并将其数据存储在两个对象中,然后将它们分组到一个 ArrayList 中,然后由该方法返回,我所指的两个对象是:

Header object 仅存储 csv 的标题(也就是 csv 的第一行)。
List(ArrayList) of GameData objects 每行 csv 动态生成。
这两个对象是不同的,它们有不同的字段和不同的方法。

             CSV
| Game  | Map      | Players | <--- Stored in a Header object      | 
| ========================== |                                     | Want to store both 
| Game1 | Panguea  | 6       | <--- | Stored in an ArrayList       | the Header and the ArrayList
| Game2 | Panguea  | 8       | <--- | containing the three objects | in a new ArrayList.
| Game3 | Medium   | 12      | <--- |                              |                                    

这里的问题是 我不能将两个不同类型的对象放入同一个 ArrayList 并且我想知道如何做到这一点(或者甚至可能),因为我想要“ load" 方法返回一个 ArrayList,这样我就可以将它用于其他功能,例如我有一个 Printer class,它有一个打印传递给它的对象的方法。

这是完成工作的方法:

public List<GameData> load(){
// List for store the data which is brought by the scanner
        mainView = new ArrayList<>();

// Scanner eluded for clarity

// Get the headers 
        String[] tableHeader = scanner.nextLine().split("\\t");
        headerFields = new Headers(tableHeader);
        mainView.add(headerFields);    

// Get the rest of the data
        while (scanner.hasNextLine()) {
            try{
                String[] elements = scanner.nextLine().split("\\t");
                mainView.add(new GameData(some params...);
            }catch (ArrayIndexOutOfBoundsException e){
                System.out.println(e);
            }
        }
        return mainView;
    }
  • 我找到了this solution,但我不喜欢它,因为这样我就会有一个空接口,只是为了分组,因为我看不到在其中创建新方法的令人信服的理由。
  • 我也不喜欢 Object 解决方案,因为这样我每次想要返回 List 中的对象时都需要转换类型。
  • 另一种解决方案是 Header 类扩展 GameData 类,这样我可以将 Header 对象放在 GameData ArrayList 中,但对我来说似乎不正确,因为 Header 不需要来自 GameData 的任何字段或方法,所以继承仅适用于该特定操作。

PD:我不能只使用一个对象来存储所有数据,因为标题(csv 的第一行)都是字符串,而 csv 中的其余行包含字符串和 int 值的混合。同样从结构上讲,它没有意义,因为每个对象都会有这些标头,这将是多余的,因为这些对象已经有同名的字段。

【问题讨论】:

  • 存储在同一个数组列表中的唯一选择是使用Object。而是创建一个新类,其中 Headers 作为成员,GameData 列表作为成员。
  • 不确定它是否适合您的用例,但我发现在使用 csv 使用 3 方库(例如 4)时它更简洁。 org.apache.commons.csv。有助于分离关注点。据我回忆,它允许读取第一行的标题,然后是其余内容。

标签: java


【解决方案1】:

我的想法是创建一个新类,它将存储对象和类。 这是一个未经测试的示例:

class ClassObject
{
 public final Class<?> type;
 public final Object instance;
 public ClassObject(Class<?> type, Object instance)
 {
  this.type = type;
  this.instance = instance;
 }
}

现在你可以创建一个 ClassObject 列表

ArrayList<ClassObject> foo;

如果您想访问某个课程,您可以执行以下操作:

switch(foo.get(i).type)
{
case ClassOne.class:
 //stuff with (ClassOne)foo.get(i).instance
 break;
case ClassTwo.class:
 //stuff with (ClassTwo)foo.get(i).instance
 break;
 //etc...
}

但这只是一个想法。我确信有更好的解决方案。

【讨论】:

  • 这比使用ArrayList&lt;Object&gt; 和instanceof 更好吗?
  • @Oleg 不是。但由于某种原因,提问者不想使用 ArrayList,所以这是一个替代方案。此外,您可以将它与 switch|case 一起使用,这样您就不必为每个可能的类添加 if 语句。
【解决方案2】:

在我看来,“Header”对象和“GameData”对象总是一起使用。如果你制作了一个具有

的“游戏”对象怎么办?
  • ArrayList 类型的“标签”实例变量
  • ArrayList 类型的“游戏”实例变量

并返回整个对象?已经过了一分钟,但我很确定您可以创建一个私有类,这实际上会使您的代码更具可读性。

【讨论】:

  • 我不知道我是否理解正确,但你说如果不是有两个类(Headers 和 GamesData)我应该有一个类(游戏)会更好然后为具有相应数据的标签和游戏创建两个实例所需的字段?我看到的问题是 GamesData 类已经有带有标题名称的字段,所以如果我将 GamesData 和标题的字段组合在一个类(游戏)中,那将是多余的,对吧?
  • 没错,在这种情况下,您可以放弃 Headers 类,而只使用 String 类型的 ArrayList 的 headers 实例
猜你喜欢
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 2017-11-13
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多