我是一个相当新手的程序员,对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但不同的attacker_ip和num_of_attacks的记录,因为该机器受到了20次攻击。第三个维度允许我这样做,但第3轴/数组对于server_id,target_ip,threat_level,client_id
是空的UPDATE 在查看答案并进行更多思考后,我想知道是否使用对象的arraylist对我来说是最好的和/或可能的。保持数据的组织和易于访问是我的一个大问题。在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
答案 0 :(得分:4)
首先,如果你有一个数组DataType[i][j]
并且j
已知是7,你可以使用的2个最大的索引是5和6,而不是6和7.这是因为Java数组索引从0开始。创建数组时,表示元素的数量,而不是最大索引(总是比元素数少一个)。
第二,当问题域已经使用多维数组 时,使用多维数组没有任何问题。我可以想到科学应用,数据分析应用,但不是更多。相反,如果您正在建模其域不使用多维数组的业务问题,那么您可能最好使用更抽象的数据结构而不是强迫数组进入设计,因为它们看起来非常高效,在其他语言中使用数组的经验更重要或其他原因。
如果没有太多信息,我会说您的“第一维度”可以更好地用List
类型表示(比如ArrayList
)。为什么?因为你说它的大小是在运行时确定的(我假设这是间接的,而不是你从某个地方获得的神奇数字)。 List
与数组类似,但具有“知道”如何成长的特殊性。您的程序可以轻松附加新元素,因为它从源中读取它们或以其他方式发现/创建它们。它也可以在开头或中间轻松插入,但这种情况很少见。
因此,您的第一个维度是:ArrayList<
某事 >
,其中某事是您第二维的类型。
关于第二个维度,你说它的大小为7,但前5个项目接受单个值,而最后2个项目接受单个值。这已经告诉我7个项目不是同质的,因此数组不明确。一个类可以更好地表示这个维度。为了理解这个类的结构,让我们说5个单值元素是同质的(类型,比如BigDecimal
)。对此最自然的表示之一是数组,因为大小已知。其余2个多值元素似乎也构成了一个数组。但是,鉴于其2个元素中的每一个都包含未识别数量的数据项,此数组的元素类型不应与前一种情况一样BigDecimal
,而是ArrayList
。这些ArrayList
s的元素类型是多个值的类型(也就是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
,thursday
和friday
执行此操作(不是saturday
}和sunday
因为这些是完全不同的东西,记得吗?),那么数组可能会更好。例如,要将商店中的商品作为数组求和,只需要:
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个项目而是1000个甚至20个,那么第二个案例中的重复将会有太多而第一个案例是首选。我也有另一个通用规则:如果我可以单独命名每个元素,那么最好这样做。如果在尝试命名元素时,我发现自己使用数字或字母顺序字母(当然,就像在月份的日子里,或者因为事情似乎没有不同的名字),那么它就是数组。即使应用这两个标准,您仍然可以找到不明确的案例。在这种情况下抛硬币,开始开发程序,并思考一下事情将如何反过来。你可以随时改变主意。
如果您的申请确实是科学的,请原谅我这么久(无用)的解释。不过,我的回答可以帮助其他人寻找类似的东西。
答案 1 :(得分:3)
使用ArrayList
代替数组基元。你可以拥有三个维度,而不会产生分配“立方体”的低效浪费
如果不创建像@nIcE cOw
这样的自定义类,那么建议Collection
对于这种事情比原始数组更加麻烦。这是因为Java喜欢冗长,并且不会为运算符重载(like C++ does)做某些事情,或者让您能够从数组中轻松实例化ArrayList
。
举例说明,使用ArrayLists的@sbat
示例;
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));
}
答案 2 :(得分: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或其他集合可能更受欢迎。