Döngü olmadan ArrayList toplamı olasılığı var mı


88

ArrayListDöngüsüz toplam olasılığı var mı ?

PHP, sum(array)dizinin toplamını verecek olanı sağlar.

PHP kodu şuna benzer:

$a = array(2, 4, 6, 8);
echo "sum(a) = " . array_sum($a) . "\n";

Ben de aynısını Java'da yapmak istedim:

List tt = new ArrayList();
tt.add(1);
tt.add(2);
tt.add(3);

2
Ya ArrayList"toplanabilir" bir şey içermiyorsa? ArrayList ve bir dizi mutlaka aynı şey değildir. Bir dizideki sayıları toplamaya gelince, bu, elemanlar üzerinde çok basit bir döngüdür ve kümülatif bir toplamı hesaplar.
posdef

PHP işlevi array_sumayrıca dahili olarak bir döngü gerçekleştirir, sadece kullanıcıdan gizler.
Paŭlo Ebermann

1
Makul bir soru. Sonuçta, bir listedeki en büyük öğeyi bulmak için bir döngü yazmak neredeyse önemsizdir, ancak java.util.Collections bir max () yöntemi sağlar.
John Velonis

1
Çok mantıklı bir soru, sonuçta, yöntemlerin amacı bu, değil mi? Reuse :)
Ben Taliadoros

Döngüler güzeldir.
Alex78191

Yanıtlar:


156

bir Zamanlar çıktı (Mart 2014) şu akışları kullanabileceksiniz :

Eğer varsa List<Integer>

int sum = list.stream().mapToInt(Integer::intValue).sum();

Eğer bir int[]

int sum = IntStream.of(a).sum();

5
mapdöngüleri örtük olarak kullanır
Nikos M.

8
Bir döngü kullanmamak için özyinelemeyi kullanabilirsiniz. : D (bunu yapma)
Caleb Fenton

23

O zaman kendin yaz:

public int sum(List<Integer> list) {
     int sum = 0; 

     for (int i : list)
         sum = sum + i;

     return sum;
}

1
Veya ArrayList'i kendi ArrayList'inizde yerleşik olarak bulundurmak için toplam yöntemiyle genişletebilirsiniz.
Bueller

3
Gerçek eklemeyi yaparken, basit kullanmak daha güzel int. Burada Integerjava'nın otomatik kutulama özellikleriyle kullanmanın çok az değeri var. Ayrıca, Integerbir Immutabletür olduğu için her seferinde potansiyel olarak birçok yeni nesne oluşturuyor ve yeniden oluşturuyorsunuz .
Java Drinker

10

Döngü kullanmanın tek alternatifi özyineleme kullanmaktır.

Gibi bir yöntem tanımlayabilirsiniz

public static int sum(List<Integer> ints) {
   return ints.isEmpty() ? 0 : ints.get(0) + ints.subList(1, ints.length());
}

Bu, düz bir döngü kullanmaya kıyasla çok verimsizdir ve listede çok sayıda öğeniz varsa patlayabilir.

Yığın taşmasını engelleyen bir alternatif kullanmaktır.

public static int sum(List<Integer> ints) {
    int len = ints.size();
    if (len == 0) return 0;
    if (len == 1) return ints.get(0);
    return sum(ints.subList(0, len/2)) + sum(ints.subList(len/2, len));
}

Bu da aynı derecede verimsizdir, ancak yığın taşmasını önleyecektir.


Aynı şeyi yazmanın en kısa yolu

int sum = 0, a[] = {2, 4, 6, 8};

for(int i: a) {
    sum += i;
}

System.out.println("sum(a) = " + sum);

baskılar

sum(a) = 20

Kodda, ilk özyinelemeli tanımdaki sum () çağrısını kaçırdınız. İkinci özyinelemeli tanım yığın taşmasının olmasını engellemez, daha az olası hale getirir.
Teudimundo

1
@Teudimundo True, Bunu engellemese de bir Listenin maksimum boyutu Tamsayı.MAX_VALUE ve log2 maksimum derinlik olan 31'dir. Çoğu sistemde sınır olarak binlerce çağrı vardır, ancak buna çok yakınsanız, yine de patlayabilir.
Peter Lawrey

9

Şunun gibi bir util işlevi yazın:

public class ListUtil{

    public static int sum(List<Integer> list){
      if(list==null || list.size()<1)
        return 0;

      int sum = 0;
      for(Integer i: list)
        sum = sum+i;

      return sum;
    }
}

O zaman beğen

int sum = ListUtil.sum(yourArrayList)

ama bunu arraylist'teki uzun değer için nasıl yapabilirim?
Ravi Parmar

5

benim için en net yol şudur:

doubleList.stream().reduce((a,b)->a+b).get();

veya

doubleList.parallelStream().reduce((a,b)->a+b).get();

Aynı zamanda dahili döngüler kullanır, ancak döngüler olmadan mümkün değildir.


2

Apache commons-collections API'sini kullanabilirsiniz.

class AggregateClosure implements org.apache.commons.collections.Closure {
        int total = 0;

        @Override
        public void execute(Object input) {
            if (input != null) {
                total += (Integer) input;
            }
        }

        public int getTotal() {
            return total;
        }
    }

Ardından bu kapağı aşağıda gösterildiği gibi kullanın:

public int aggregate(List<Integer> aList) {
        AggregateClosure closure = new AggregateClosure();
        org.apache.commons.collections.CollectionUtils.forAllDo(aList, closure);
        return closure.getTotal();
}

1

Harita işlevini biliyorsanız, bir haritanın da özyinelemeli döngü veya özyinelemeli döngü olabileceğini bilirsiniz. Ancak bunun için her bir unsura ulaşmanız gerektiği açık. bu yüzden, Java 8'i çözemedim, çünkü bazı sözdizimi uyumsuzluğu ama çok kısa olmasını istedim, bu yüzden elimde olan bu.

int sum = 0
for (Integer e : myList) sum += e;

Haklısın. Bunun harita yerine, arka arkaya yinelemeli olabilen minimal bir döngü olduğunu söyledim.
sivi

"Döngü olmadan ArrayList toplamı olasılığı var mı?"
alexander

0

Bir listenin her türden nesneyi tutabileceği düşünüldüğünde, tüm öğeleri toplamanıza izin veren yerleşik bir yöntem yoktur. Bunun gibi bir şey yapabilirsiniz:

int sum = 0;

for( Integer i : ( ArrayList<Integer> )tt ) {
  sum += i;
}

Alternatif olarak, ArrayList'ten miras alan ama aynı zamanda yukarıdaki kodu uygulayan sum () adında bir yöntemi uygulayan kendi konteyner türünüzü oluşturabilirsiniz.


0

ArrayList bir öğeler koleksiyonudur (liste biçiminde), ilkel, sarmalayıcı sınıf nesnesi olarak depolanır, ancak aynı zamanda String sınıfının nesnelerini de depolayabilirim. SUM bunda bir anlam ifade etmeyecektir. BTW neden döngü için (geliştirilmiş veya yineleyici aracılığıyla) kullanmaktan bu kadar korkuyorsunuz?


0

Veya Groovy'ye geçin, bir koleksiyonda bir sum () işlevi vardır. [1,2,3,4,5,6] .sum ()

http://groovy.codehaus.org/JN1015-Collections

Java sınıflarınızla aynı JVM üzerinde çalışır.


8
Evet. Toplama işlevi kesinlikle başka bir dile geçmek için bir nedendir. : D
ruX

1
Soru etiketlendi Java, bu nedenle bu teknik olarak geçerli bir cevap değil.
Bengt

0

Bu bağlantı , java'da toplamanın üç farklı yolunu gösterir, Apache Commons Math kullanarak önceki cevaplarda olmayan bir seçenek vardır ..

Misal:

public static void main(String args []){
    List<Double> NUMBERS_FOR_SUM = new ArrayList<Double>(){
         {
            add(5D);
            add(3.2D);
            add(7D);
         }
    };
    double[] arrayToSume = ArrayUtils.toPrimitive(NUMBERS_FOR_SUM
            .toArray(new Double[NUMBERS_FOR_SUM.size()]));    
    System.out.println(StatUtils.sum(arrayToSume));

}

Bkz StatUtils api


0

GNU Trove kitaplığını kullanabilirsiniz :

TIntList tt = new TIntArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
int sum = tt.sum();

0

Bu, yöntem referansları kullanılarak azaltma ile yapılabilir reduce(Integer::sum):

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(Integer::sum)
        .get();

Veya olmadan Optional:

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(0, Integer::sum);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.