3

我是一个相当新手的程序员,有一个关于 Java 数组的问题。考虑一个二维数组,[i][j]。i 的值在运行时确定。j 的值已知为 7。在 [i][6] 和 [i][7] 我希望能够存储更深的数组或值列表。是否可以在数组中有类似数组的东西,其中在 [i][6] 和 i[7] 点有 x 和 y 轴和 z 轴,或者我需要一个完整的 3D 内存立方体来能够存储和浏览我的数据吗?

详细信息:我的目标是运行一个查询,该查询从两个表(目标和攻击者)中获取某些信息我的查询很好,我可以得到一个结果集。我真正想做的是存储我的结果集中的数据,并以更有用的格式将其呈现在表格中,同时在数据可视化程序中使用它。我得到的字段是:server_id、target_ip、threat_level、client_id、attacker_ip 和 num_of_attacks。我可以获得 20 条具有相同 server_id、target_ip、threat_level、client_id 但不同的攻击者 IP 和 num_of_attacks 的记录,因为该机器受到了 20 次攻击。第三个维度允许我这样做,但对于 server_id、target_ip、threat_level、client_id,第三个轴/数组将为空

在查看答案并进行更多思考后更新我想知道使用对象数组列表是否最适合我和/或可能。保持数据井井有条且易于访问对我来说是一个大问题。在psedu代码中它会是这样的:

Object[] servers
    String server_id
    String target
    String threat_level
    String client_id
    String arr[][]   // this array will hold attacker_ip in one axis and num_of_attacks in the other in order to keep the relation between the attacking ip and the number of attacks they make against one specific server
4

3 回答 3

4

首先,如果您有一个数组DataType[i][j]并且j已知为 7,那么您可以使用的 2 个最大索引是 5 和 6,而不是 6 和 7。这是因为 Java 数组索引是从 0 开始的。创建数组时,您指示元素的数量,而不是最大索引(它总是比元素数量少一)。

其次,当问题域已经使用多维数组时,使用多维数组并没有错。我可以想到科学应用、数据分析应用,但不多。相反,如果您正在建模一个其领域不使用多维数组的业务问题,您可能最好使用更抽象的数据结构,而不是仅仅因为数组看起来非常高效而将它们强制纳入设计,请在其他语言中使用数组是更重要,还是其他原因。

在没有太多信息的情况下,我会说您的“第一维”可以更好地用一种List类型(比如ArrayList)来表示。为什么?因为你说它的大小是在运行时确定的(我假设这是间接的,而不是你从某个地方获得的幻数)。 Lists 类似于数组,但具有它们“知道”如何增长的特殊性。您的程序可以在从源中读取新元素或以其他方式发现/创建它们时轻松附加新元素。它也可以很容易地将它们插入到开头或中间,但这种情况很少见。

因此,您的第一个维度将是: ArrayList<something>,其中something是您的第二个维度的类型。

关于第二个维度,您说它的大小为 7,但前 5 个项目接受单个值,而后 2 个项目接受多个值。这已经告诉我这 7 个项目不是同质的,因此数组是不正确的。这个维度最好用一个类来表示。为了理解这个类的结构,假设 5 个单值元素是同质的(类型,比如BigDecimal)。最自然的表示之一是数组,因为它的大小是已知的。剩下的 2 个多值元素似乎也构成了一个数组。但是,鉴于它的 2 个元素中的每一个都包含未知数量的数据项,因此该数组的元素类型不应BigDecimal与前一种情况一样,而是ArrayList. 这些元素的类型ArrayLists 是多个值的类型(也可以说BigDecimal)。

最终结果是:

class SecondD {
    BigDecimal[] singleValued= new BigDecimal[5] ;
    ArrayList<BigDecimal>[] multiValued= new ArrayList<BigDecimal>[2] ;
    {
        multiValued[0]= new ArrayList<BigDecimal>() ;
        multiValued[1]= new ArrayList<BigDecimal>() ;
    }
}
ArrayList<SecondD> data= new ArrayList<SecondD>() ;

在这个代码片段中,我不仅要声明结构,还要创建它们以便它们可以使用。纯粹的声明将是:

class SecondD {
    BigDecimal[] singleValued;
    ArrayList<BigDecimal>[] multiValued;
}
ArrayList<SecondD> data= new ArrayList<SecondD>() ;

从类型(因此是结构)的角度来看,数组大小在 Java 中并不重要。这就是为什么你看不到任何 5 或 2。

访问数据结构就像

data.get(130).singleValued[2]
data.get(130).multiValued[1].get(27)

在某些情况下可能更清楚的可能变体是

class SecondD {
    BigDecimal monday;
    BigDecimal tuesday;
    BigDecimal wednesday;
    BigDecimal thursday;
    BigDecimal friday;
    ArrayList<BigDecimal> saturday= new ArrayList<BigDecimal>() ;
    ArrayList<BigDecimal> sunday= new ArrayList<BigDecimal>() ;
}
ArrayList<SecondD> data= new ArrayList<SecondD>() ;

在这种情况下,我们将每个数组“扩展”为单独的项目,每个项目都有一个名称。典型的访问操作是:

data.get(130).wednesday
data.get(130).sunday.get(27)

选择哪种变体?嗯,这取决于不同项目的操作有多么相似或不同。如果每次您执行和操作时,monday您也将执行它tuesday, wednesday, , thursdayand friday(不是因为这些是完全不同的东西,还记得吗?),那么数组可能会更好。例如,要将存储为数组时的项目求和,只需:saturdaysunday

element= data.get(130) ;
int sum= 0 ;
for(int e: element.singleValued ) sum+= e ;

而如果展开:

element= data.get(130) ;
int sum= 0 ;
sum+= element.monday ;
sum+= element.tuesday ;
sum+= element.wednesday ;
sum+= element.thursday ;
sum+= element.friday ;

在这种情况下,只有 5 个元素,差异并不大。第一种方法使事情变得更短,而第二种方法使它们更清晰。就个人而言,我投票赞成明确。现在,如果不是 5 个项目,而是 1,000 个或什至少到 20 个,则第二种情况下的重复将太多,而第一种情况更受欢迎。我对此也有另一个一般规则:如果我可以分别命名每个元素,那么最好这样做。如果在尝试命名元素时,我发现自己使用数字或字母的连续字母(自然地,如一个月中的日子,或者因为事物似乎没有不同的名称),那么它就是数组。即使应用了这两个标准,您仍然可以找到不清楚的案例。本例抛硬币,开始开发程序,想一想事情会是怎样的另一种方式。你可以随时改变主意。

如果你的申请确实是科学的,请原谅我这么长(而且没用)的解释。不过,我的回答可以帮助其他人寻找类似的东西。

于 2013-08-10T07:58:23.803 回答
3

使用ArrayList而不是数组原语。您可以拥有三个维度,而不会因分配“立方体”而导致相关的低效浪费


如果不创建像@nIcE cOw建议这样的自定义Collection类比原始数组更麻烦。这是因为 Java 喜欢冗长,并且不会为您做某些事情,例如运算符重载(就像 C++ 所做的那样),或者让您能够轻松地ArrayList从数组中实例化。

举例来说,@sbat这是 ArrayLists 的示例;

public static <T> ArrayList<T> toAL(T ... input) {
    ArrayList<T> output = new ArrayList<T>();
    for (T item : input) {
        output.add(item);
    }
    return output;
}

public static void main(String[] args) {
    ArrayList<ArrayList<ArrayList<Integer>>> a = toAL(
        toAL(
            toAL(0, 1, 2)
        ),
        toAL(
            toAL(4, 5)
        ),
        toAL(
            toAL(6)
        )
    );
    System.out.println(a.get(0).get(0).get(2));
    System.out.println(a.get(1).get(0).get(1));
    System.out.println(a.get(2).get(0).get(0));
}
于 2013-08-10T05:49:59.307 回答
2

当然,这样做在语法上没有任何问题:

int[][][] a = {{{0, 1, 2}}, {{4, 5}}, {{6}}};
System.out.println(a[0][0].length); // 3
System.out.println(a[1][0].length); // 2
System.out.println(a[2][0].length); // 1

事实上,这就是 Java 中的多维数组,它们是数组中的数组。我看到的唯一问题是它以后可能会变得混乱或难以维护,但在 ArrayLists 中使用 ArrayLists 也会如此:

List<List<List<Integer>>> list = ...;
System.out.println(list.get(0).get(1).get(50)); // using ArrayList

但是,您可能更喜欢数组而不是集合仍然是有原因的。但根据具体情况,ArrayLists 或其他集合可能更可取。

于 2013-08-10T06:02:17.357 回答