如何使用数组列表作为字段有效地深度克隆对象数组

how to efficiently deep clone an array of objects with an arraylist as a field

最深元素:

class Player {
    //fields contain:
    int value;
}

收集于:

class Team {
    //fields contain:
    ArrayList<Player> players;
}

收集于:

class Splitter {
    //fields contain:
    Teams[] teams;
}

Splitter 的函数中,我必须克隆 teams。我基本上必须通过克隆每个 Team 对象来克隆数组 teams,每个对象都包含一个我必须克隆的 ArrayList players。我不想自己克隆播放器对象。

到目前为止,我的解决方案如下所示:

private Team[] deepClone(Team[] teams) {
    Team[] new_teams = new Team[teams.length];
    for (int i = 0; i < teams.length; i++) {
        new_teams[i] = new Team();
        for (Player player : teams[i].getPlayers())
            new_teams[i].getPlayers().add(player);
    }
    return new_teams;
}

有什么我可以更改以使其更高效或更优雅的吗?

您当前的解决方案相当于这个更简单的形式:

private Team[] deepClone(Team[] teams) {
    Team[] new_teams = new Team[teams.length];
    for (int i = 0; i < teams.length; i++) {
        new_teams[i] = new Team();
        new_teams[i].getPlayers().addAll(teams[i].getPlayers());
    }
    return new_teams;
}

您可以在没有循环索引的情况下使用流和 lambda 使它更优雅:

private Team[] deepClone(Team[] teams) {
    return Stream.of(teams).map(team -> {
        Team newTeam = new Team();
        return newTeam.getPlayers().addAll(team.getPlayers());
    }).toArray(Team[]::new);
}

理想情况下,如果你想进行完美的深度克隆,你也应该克隆玩家,我们应该始终在每个 class 中编写克隆方法,然后调用该克隆方法来获得克隆,无论如何你可以通过以下方式进行。

class Team {
        //fields contain:
        ArrayList<Player> players;
        public Team clone() {
           Team team = new Team();
           team.players.addAll(players);
           return team;
        }
    }

// ...

    Team[] deepCloneTeams(Team[] teams) {
        Team[] newTeams = new Team[teams.length];
        for (int i = 0; i < teams.length; i++)
            newTeams[i] = teams[i].clone();
        return newTeams;
    }