Java 是否有比ArrayList更适合此场景的集合?

Java 是否有比ArrayList更适合此场景的集合?,java,arraylist,Java,Arraylist,我有一个方法需要返回一组数据,当前的计划是使用ArrayList of ArrayList,但是我不确定是否有更合适的集合 集合具有固定数量的行。每个集合有n个组,这将保持不变 集合具有固定数量的数据项。它们只是以未知的分布方式分布在集合的各行中 在输入数据完成处理之前,我们不知道每行的长度 这种抽象性质使我相信,每一行最好由一个ArrayList表示,因为在最终将该ArrayList添加到主ArrayList之前,可以向其中添加条目 是否有更好的方法来做到这一点,特别是在性能方面?如果行数

我有一个方法需要返回一组数据,当前的计划是使用ArrayList of ArrayList,但是我不确定是否有更合适的集合

  • 集合具有固定数量的行。每个集合有n个组,这将保持不变
  • 集合具有固定数量的数据项。它们只是以未知的分布方式分布在集合的各行中
  • 在输入数据完成处理之前,我们不知道每行的长度
这种抽象性质使我相信,每一行最好由一个ArrayList表示,因为在最终将该ArrayList添加到主ArrayList之前,可以向其中添加条目


是否有更好的方法来做到这一点,特别是在性能方面?

如果行数是固定的(假设为10),列数不是固定的,那么您可以使用列表数组,例如:

// Use whatever type you need instead of Integer.
@SuppressWarnings("unchecked")
List<Integer>[] arrayOfLists = new ArrayList[10];
//使用所需的任何类型而不是整数。
@抑制警告(“未选中”)
列表[]arrayOfLists=新的ArrayList[10];

此代码发出警告“通用数组创建”。出于这个原因,我添加了
@SuppressWarnings(“unchecked”)

没有什么复杂的方法(但由于可以直接访问数据,所以性能很好)如何使集合具有由groupKey(rowKey)表示的行和由comlunKey表示的列。在这里可以添加可选对象。 简单地说,这就是地图中的地图

/**
 * representation of bi dimensional array with dynamical size
 *
 * @param <K> - type of row key
 * @param <L> - type of columne key
 * @param <V> - type of value
 */
public class CustomCollection<K, L, V> extends HashMap<K, Map<L, V>> {

public CustomCollection() {

}

/**
 * add new entry on particular row and column
 *
 * @param rowKey    - key of row
 * @param columnKey - key of column
 * @param value     - value to add
 */
public void addNewEntry(K rowKey, L columnKey, V value) {
    Map<L, V> columns = get(rowKey);
    if (columns == null) {
        columns = new HashMap<>();
        put(rowKey, columns);
    }
    columns.put(columnKey, value);
}

/**
 * get exact value on current row represented by {@code rowKey} and column represented by {@code columnKey}
 *
 * @param rowKey    - key of row
 * @param columnKey - key of column
 * @return
 */
public V getExactValue(K rowKey, V columnKey) {
    Map<L, V> columns = get(rowKey);
    if (columns == null) {
        return null;
    }
    return columns.get(columnKey);
}

/**
 * get colums values as map
 *
 * @param rowKey - key of row
 * @return
 */
public Map<L, V> getColumsAsMap(K rowKey) {
    return get(rowKey);
}

/**
 * get colums values as map
 *
 * @param rowKey - key of row
 * @return
 */
public Collection<V> getColumsAsCollection(K rowKey) {
    Map<L, V> columns = get(rowKey);
    if (columns == null) {
        return null;
    }
    return columns.values();
}

/**
 * remove value on particular index
 *
 * @param rowKey
 * @param columnKey
 *
 * @return - removed item
 */
public V removeExactValue(K rowKey, L columnKey){
    Map<L, V> columns = get(rowKey);
    if (columns == null) {
        return null;
    }
    return columns.remove(columnKey);
}

@Override
public String toString(){
    final StringBuffer stringBuffer = new StringBuffer();
    keySet().forEach(rowKey -> {
        stringBuffer.append(rowKey + " = {");
        Map<L, V> columns = get(rowKey);
        if (columns != null) {
            columns.entrySet().forEach(entry -> {
                stringBuffer.append("["+entry.getKey()+"="+entry.getValue()+"]");
            });
        }
        stringBuffer.append("}\n");
    });
    return stringBuffer.toString();
}
}

// Sample how to use it

public static void main(String [] args){
    CustomCollection<Integer,Integer,String> customCollection = new CustomCollection<>();
    customCollection.addNewEntry(1,1, "v_1_1");
    customCollection.addNewEntry(1,2,"v_1_2");
    customCollection.addNewEntry(2,1,"v_2_1");
    customCollection.addNewEntry(2,2,"v_2_2");
    customCollection.addNewEntry(2,3,"v_2_3");
    System.out.println(customCollection.toString());
    System.out.println("After remove:");
    customCollection.removeExactValue(2,2);
    customCollection.removeExactValue(2,3);
    System.out.println(customCollection.toString());
}
/**
*具有动态尺寸的二维阵列表示
*
*@param-行键的类型
*@param-列键的类型
*@param-值的类型
*/
公共类CustomCollection扩展了HashMap{
公共收藏(){
}
/**
*在特定行和列上添加新条目
*
*@param rowKey-行的键
*@param columnKey-列的键
*@param value-要添加的值
*/
public void addNewEntry(K行键、L列键、V值){
Map columns=get(rowKey);
如果(列==null){
columns=newhashmap();
put(行键、列);
}
columns.put(columnKey,value);
}
/**
*获取由{@code rowKey}表示的当前行和由{@code columnKey}表示的列的精确值
*
*@param rowKey-行的键
*@param columnKey-列的键
*@返回
*/
public V getExactValue(K行键,V列键){
Map columns=get(rowKey);
如果(列==null){
返回null;
}
返回columns.get(columnKey);
}
/**
*获取列值作为映射
*
*@param rowKey-行的键
*@返回
*/
公共地图GetColumnSasMap(K行键){
返回get(rowKey);
}
/**
*获取列值作为映射
*
*@param rowKey-行的键
*@返回
*/
公共集合GetColumnSasCollection(K行键){
Map columns=get(rowKey);
如果(列==null){
返回null;
}
返回columns.values();
}
/**
*删除特定索引上的值
*
*@param rowKey
*@param-columnKey
*
*@return-已移除物品
*/
public V removeExactValue(K行键,L列键){
Map columns=get(rowKey);
如果(列==null){
返回null;
}
返回列。删除(columnKey);
}
@凌驾
公共字符串toString(){
final StringBuffer StringBuffer=新StringBuffer();
keySet().forEach(行键->{
追加(rowKey+“={”);
Map columns=get(rowKey);
if(列!=null){
columns.entrySet().forEach(条目->{
stringBuffer.append(“[”+entry.getKey()+“=”+entry.getValue()+“]);
});
}
stringBuffer.append(“}\n”);
});
返回stringBuffer.toString();
}
}
//示例如何使用它
公共静态void main(字符串[]args){
CustomCollection CustomCollection=新建CustomCollection();
customCollection.addNewEntry(1,1,“v_1_1”);
customCollection.addNewEntry(1,2,“v_1_2”);
customCollection.addNewEntry(2,1,“v_2_1”);
customCollection.addNewEntry(2,2,“v_2_2”);
customCollection.addNewEntry(2,3,“v_2_3”);
System.out.println(customCollection.toString());
System.out.println(“删除后:”);
customCollection.removeExactValue(2,2);
customCollection.removeExactValue(2,3);
System.out.println(customCollection.toString());
}

在Java中,有锯齿状数组的概念。基本上和你描述的一样。您可以通过以下两种方式之一实现它

  • 一个二维数组,在其中声明变量时初始化行,在需要使用变量时声明每一列
  • 一个列表数组,初始化时在其中声明行,并在需要时向行中的每个索引添加项(列)
  • 二维阵列方法

    // Initialize the rows only for now
    String[][] arr = new String[3][];
    
    // Process some data to know the column sizes of each
    // ...
    arr[0] = new String[] {"Foo", "Bar", "FooBar"};
    arr[1] = new String[] {"Jane", "Doe"};
    arr[2] = new String[] {"Peter", "Parker", "Tony", "Stark"};
    // ...
    // Printing 
    for(String[] row : arr) {
        System.out.println(Arrays.ToString(row));
    }
    
    // Initialize the rows only for now
    List<String> [] arr = new List[3];
    
    // Process some data
    // ...
    List<String> list1 = new ArrayList<>();
    list1.add("Foo");
    list1.add("Bar");
    list1.add("FooBar");
    List<String> list2 = new ArrayList<>();
    list2.add("Jane");
    list2.add("Doe");
    List<String> list3 = new ArrayList<>();
    list3.add("Peter");
    list3.add("Parker");
    list3.add("Tony");
    list3.add("Stark");
    // ...
    // Printing
    for(int i = 0 ; i < arr.length; i++) {
        List<String> temp = arr[i];
        System.out.println(temp);
    }
    
    列表数组方法

    // Initialize the rows only for now
    String[][] arr = new String[3][];
    
    // Process some data to know the column sizes of each
    // ...
    arr[0] = new String[] {"Foo", "Bar", "FooBar"};
    arr[1] = new String[] {"Jane", "Doe"};
    arr[2] = new String[] {"Peter", "Parker", "Tony", "Stark"};
    // ...
    // Printing 
    for(String[] row : arr) {
        System.out.println(Arrays.ToString(row));
    }
    
    // Initialize the rows only for now
    List<String> [] arr = new List[3];
    
    // Process some data
    // ...
    List<String> list1 = new ArrayList<>();
    list1.add("Foo");
    list1.add("Bar");
    list1.add("FooBar");
    List<String> list2 = new ArrayList<>();
    list2.add("Jane");
    list2.add("Doe");
    List<String> list3 = new ArrayList<>();
    list3.add("Peter");
    list3.add("Parker");
    list3.add("Tony");
    list3.add("Stark");
    // ...
    // Printing
    for(int i = 0 ; i < arr.length; i++) {
        List<String> temp = arr[i];
        System.out.println(temp);
    }
    
    //现在只初始化行
    列表[]arr=新列表[3];
    //处理一些数据
    // ...
    List list1=新的ArrayList();
    清单1.添加(“Foo”);
    清单1.添加(“酒吧”);
    清单1.添加(“FooBar”);
    List list2=新的ArrayList();
    清单2.添加(“简”);
    清单2.添加(“Doe”);
    List list3=新的ArrayList();
    清单3.添加(“彼得”);
    清单3.添加(“帕克”);
    清单3.添加(“托尼”);
    清单3.添加(“斯塔克”);
    // ...
    //印刷品
    对于(int i=0;i
    根据您的需要,因为您知道您的数据集将始终保持固定。您只是不知道锯齿数组中每行的长度。基于此,采用平面二维方法

    现在,如果您认为以后需求会发生变化,或者您喜欢
    ArrayLists
    拥有的有用方法(
    contains
    等),那么我会选择
    ArrayLists
    Array

    除非数据集非常庞大,否则您不会注意到这两种实现之间的显著性能差异。如果您正在经历性能测试