すべての配列要素をゼロに初期化するショートカットはありますか?


281

ではC/C++私が行うために使用しました

int arr[10] = {0};

...すべての配列要素を0に初期化します。

Javaにも同様のショートカットはありますか?

ループの使用を避けたいのですが可能ですか?

int arr[] = new int[10];
for(int i = 0; i < arr.length; i++) {
    arr[i] = 0;
}

2
java.util.Arrays.fill()int [] arr = new int [10]; およびint arr [10] = {0}; すべて内部ループを使用します。
Kevin Kostlan、2012

回答:


574

整数型の配列のデフォルト値0は、言語仕様で保証されています

各クラス変数、インスタンス変数、または配列コンポーネントは、作成時にデフォルト値で初期化されます(§15.9、§15.10)[...] typeのint場合、デフォルト値はゼロ、つまりです0。  

1次元配列を別の値に初期化する場合は、java.util.Arrays.fill()を使用できますもちろん内部的にループを使用します)。


@MichaelBorgwardt私に役立つ回答でした。forループと比較すると、同じコストがかかりますか?
メイサム-ɯɐɥʇʎɐɯ2015

@maytham-ɯɐɥıλɐɯ:JDKに付属しているソースコードを確認できます。それはまったく同じです。メソッドは、完全に通常の単純なforループのみで構成されます。
Michael Borgwardt 2015

@MichaelBorgwardtローカルの2次元配列の値はどうですか?それは「配列コンポーネント」に該当しますか?
リシ

Arrays.fill必ずしもループを使用する必要はありません。
NateS 2017年

@NateS:できないJava実装の例を挙げられますか?
Michael Borgwardt 2017年

104

他の答えは正しいですが(int配列の値はデフォルトで0に初期化されます)、明示的にそうしたい場合(たとえば、値42で満たされた配列が必要な場合など)は、以下のfill()メソッドを使用できます。配列クラス:

int [] myarray = new int[num_elts];
Arrays.fill(myarray, 42);

または、ワンライナーのファンなら、次のCollections.nCopies()ルーチンを使用できます。

Integer[] arr = Collections.nCopies(3, 42).toArray(new Integer[0]);

arrに値を与えます:

[42, 42, 42]

(そうでIntegerはありませintんが、プリミティブ型が必要な場合は、Apache CommonsArrayUtils.toPrimitive()ルーチンに従うことができます:

int [] primarr = ArrayUtils.toPrimitive(arr);

9
ワンライナーは良いですがList<Integer>Integer[]int[]?それは少し複雑です。
dhardy 2013年

2
@dhardyもちろんですが、そのため2行バージョンも回答に含まれています(「複雑な」要因が心配な場合)。
アダムパーキン2013年

Arrays.fillメソッドで2D配列を初期化すると問題が発生し、エラーが発生します。
AKS

39

Javaでは、すべての要素(プリミティブ整数タイプはbyte shortintlong)デフォルトで0に初期化されます。ループを保存できます。


2
これはプリミティブ型に当てはまると思いますか?!
Olimpiu POP 2013

1
intのようなプリミティブJavaタイプは初期化されません。
Mirko Ebert 2014

8
@ tfb785:これは間違っています。マイケルBorgwardtによって上述のように:プリミティブ整数型(長い、短い、INTは、)は0に初期化される
アルネドイツ

1
INTのようなJavaプリミティブの配列は[] 0なしで開始されているはい、一つのJavaプリミティブ型は、0で開始されていない
ミルコエバート

3
正確には、プリミティブクラスメンバー(静的かどうかにかかわらず)は0で初期化されます。ローカル変数はそうではありません。
Arne Deutsch 2014

23

アプリケーションのパフォーマンスをどのように低下​​させるか... 以下をお読みください。

Java言語仕様では、オブジェクトのデフォルト/初期値を次のように指定できます。

タイプbyteデフォルト値0です。つまり、(byte)の値は0です。

型のために短いデフォルト値はであるゼロである、(ショート)の値は、0

タイプintの場合、デフォルト値0、つまり0です。

long型の場合、デフォルト値0、つまり0Lです。

float型の場合、デフォルト値正のゼロ、つまり0.0fです。

double型の場合、デフォルト値正のゼロ、つまり0.0dです。

char型の場合、デフォルト値ヌル文字、つまり「\ u0000」です。

型の場合はブール値デフォルト値はです

以下のために、すべての参照型デフォルト値があるヌル

これらすべてを考慮することで、配列要素のゼロ値で初期化する必要はありません。デフォルトでは、すべての配列要素はint配列では0だからです。

なぜなら、配列は、単一の型の固定数の値を保持するコンテナオブジェクトだからです。配列のTypeはintなので、すべての配列要素のデフォルト値がint typeを保持しているため、自動的に0になることを考慮してください。

次に、すべての配列要素のデフォルト値nullになるように、String型配列検討ます

なんでそんなことしないの……?

質問で提案するようにループを使用してnull値を割り当てることができます。

int arr[] = new int[10];
for(int i=0;i<arr.length;i++)
    arr[i] = 0;

しかし、そのようにすると、マシンサイクルが無駄に失われます。多数のアレイがあるアプリケーションで使用し、各アレイに対してそれを行うと、アプリケーションのパフォーマンスにかなりのレベルまで影響します。

マシンサイクルのより多くの利用==>データ処理に多くの時間==>出力時間が大幅に増加されます。アプリケーションのデータ処理を低レベルと見なすことができるようにします(ある程度のレベルまでスロー)。


17

ループを保存できます。初期化はすでに0になっています。ローカル変数の場合も同様です。

ただし、読みやすくするために、ブラケットを配置する場所を修正してください(ベストプラクティスとして認識されています)。

int[] arr = new int[10];

14

FloatまたはIntegerを使用している場合は、次のようにデフォルト値を割り当てることができます...

Integer[] data = new Integer[20];
Arrays.fill(data,new Integer(0));

6

既存の配列サイズで新しい空の配列を作成し、それらを配列に割り当てることができます。これは他のものより速いかもしれません。スニペット:

package com.array.zero;
public class ArrayZero {
public static void main(String[] args) {
    // Your array with data
    int[] yourArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    //Creating same sized array with 0
    int[] tempArray = new int[yourArray.length];
    Assigning temp array to replace values by zero [0]
    yourArray = tempArray;

    //testing the array size and value to be zero
    for (int item : yourArray) {
        System.out.println(item);
    }
}
}

結果:

0
0
0
0
0    
0
0
0
0

1

はい、配列のint値はゼロに初期化されます。しかし、これは保証されていません。Oracleのドキュメントでは、これは不適切なコーディング方法であると述べています。


Java言語仕様のセクション15.10.2によると、配列が初期値を提供しない配列作成例外で作成された場合、配列のすべての要素は、配列のコンポーネントタイプのデフォルト値(つまり0)に初期化されます。 char []の場合。これは保証です。オラクルがそれに依存することは悪い習慣だと考えられていることに私はかなり驚きます。
Ian Robertson

1

みんなが言ったように、int値は初期化後すでにゼロです。実際に配列値をゼロに設定する必要があり、それを最適化したい場合は、次を使用しますSystem.arraycopy

static private int[] zeros = new float[64];
...
int[] values = ...
if (zeros.length < values.length) zeros = new int[values.length];
System.arraycopy(zeros, 0, values, 0, values.length);

これはmemcpy、ほとんどまたはすべてのJRE実装で内部的に使用されます。最悪の場合、複数のスレッドがzeros同時に再割り当てされ、何も害を及ぼさないため、このようなstaticの使用は複数のスレッドでも安全です。

Arrays.fill他の人が述べたように使用することもできます。Arrays.fill memcpyスマートJVMで使用できますが、おそらくJavaループとそれに伴う境界チェックにすぎません。

もちろん、最適化のベンチマークを行います。


1

Java 8より上のラムダを使用したさらに別のアプローチ

 Arrays.stream(new Integer[nodelist.size()]).map(e -> 
 Integer.MAX_VALUE).toArray(Integer[]::new);

1

c / cppにはショートカットはありませんが、すべての配列をゼロの添え字で初期化する必要があります。例:

  int arr[10] = {0};

しかし、JavaにはArrays.fill()と呼ばれる魔法のツールがあり、選択した整数で配列のすべての値を埋めます。例:

  import java.util.Arrays;

    public class Main
    {
      public static void main(String[] args)
       {
         int ar[] = {2, 2, 1, 8, 3, 2, 2, 4, 2};
         Arrays.fill(ar, 10);
         System.out.println("Array completely filled" +                          
            " with 10\n" + Arrays.toString(ar));
   }
 }

1

Javaのintのデフォルト値はゼロであるため、ゼロの場合は初期化は不要です。ゼロ以外の値の場合java.util.Arrays、いくつかのオプションが提供されますが、最も簡単なのはfillメソッドです。

int[] arr = new int[5];
Arrays.fill(arr, -1);
System.out.println(Arrays.toString(arr));  //[-1, -1, -1, -1, -1 ]

int [] arr = new int[5];
// fill value 1 from index 0, inclusive, to index 3, exclusive
Arrays.fill(arr, 0, 3, -1 )
System.out.println(Arrays.toString(arr)); // [-1, -1, -1, 0, 0]

条件に基づいて値を入力する場合は、Arrays.setAll()を使用することもできます。

int[] array = new int[20];
Arrays.setAll(array, p -> p > 10 ? -1 : p);

int[] arr = new int[5];
Arrays.setAll(arr, i -> i);
System.out.println(Arrays.toString(arr));   // [0, 1, 2, 3, 4]

0

配列をクラス内のインスタンス変数として宣言します。つまり、すべてのメソッドから配列を宣言すると、JVMはデフォルト値として0を指定します。もう心配する必要はありません


-3
    int a=7, b=7 ,c=0,d=0;
    int dizi[][]=new int[a][b];
    for(int i=0;i<a;i++){
        for(int q=d;q<b;q++){
            dizi[i][q]=c;               
            System.out.print(dizi[i][q]);
            c++;
        }

        c-=b+1;
        System.out.println();               
    }

結果0123456 -1012345 -2-101234 -3-2-10123 -4-3-2-1012 -5-4-3-2-101 -6-5-4-3-2-10

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.