การหาค่า max / min ในอาร์เรย์ของ primitives โดยใช้ Java


185

การเขียนฟังก์ชันเพื่อกำหนดค่า min / max ในอาเรย์นั้นเป็นเรื่องเล็กน้อยเช่น:

/**
 * 
 * @param chars
 * @return the max value in the array of chars
 */
private static int maxValue(char[] chars) {
    int max = chars[0];
    for (int ktr = 0; ktr < chars.length; ktr++) {
        if (chars[ktr] > max) {
            max = chars[ktr];
        }
    }
    return max;
}

แต่นี่ไม่ใช่สิ่งที่ทำไปแล้วเหรอ?


8
อาร์เรย์ของดั้งเดิมไปยังอาร์เรย์ของภาชนะบรรจุที่จะช่วยให้: stackoverflow.com/questions/3770289/...Collections.max(Arrays.asList())ตามมาด้วย
Ciro Santilli 郝海东冠状病六四事件法轮功

ฉันชอบที่ Java เป็นใบ้แค่ไหน
Farid

คำตอบ:


173

ใช้คอมมอนส์ Lang (เพื่อแปลง) + คอลเลกชัน (ถึงนาที / สูงสุด)

import java.util.Arrays;
import java.util.Collections;

import org.apache.commons.lang.ArrayUtils;

public class MinMaxValue {

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};

        List b = Arrays.asList(ArrayUtils.toObject(a));

        System.out.println(Collections.min(b));
        System.out.println(Collections.max(b));
   }
}

โปรดทราบว่าArrays.asList()ล้อมอาร์เรย์พื้นฐานดังนั้นจึงไม่ควรมีหน่วยความจำมากเกินไปและไม่ควรทำสำเนาองค์ประกอบของอาร์เรย์


9
คืออะไรArrayUtils
Basheer AL-MOMANI

4
Arrays.asList()ควรจะปรับ แต่ArrayUtils.toObject()จะคัดลอกองค์ประกอบของแต่ละเป็นแถวใหม่a Character
EM

5
Arrays.asList(a)ไม่ทำงาน คุณไม่สามารถสร้างรายการดั้งเดิมได้ ( List<char>ในกรณีนี้) ก่อนอื่นคุณต้องแปลงค่าดั้งเดิมเป็นวัตถุและนั่นคือสาเหตุที่ArrayUtils.toObjectใช้
nessa.gp

96

คุณก็สามารถใช้ Java ใหม่ 8 Streamsintแต่คุณจะต้องทำงานร่วมกับ

streamวิธีการของการเรียนยูทิลิตี้Arraysจะช่วยให้คุณIntStreamที่คุณสามารถใช้minวิธีการ นอกจากนี้คุณยังสามารถทำmax, sum, average...

getAsIntวิธีการที่ใช้ในการรับค่าจากที่OptionalInt

import java.util.Arrays;

public class Test {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        int min = Arrays.stream(tab).min().getAsInt();
        int max = Arrays.stream(tab).max().getAsInt();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max)
    }

}

== == UPDATE

หากเวลาดำเนินการมีความสำคัญและคุณต้องการผ่านข้อมูลเพียงครั้งเดียวคุณสามารถใช้summaryStatistics()วิธีการเช่นนี้

import java.util.Arrays;
import java.util.IntSummaryStatistics;

public class SOTest {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
        int min = stat.getMin();
        int max = stat.getMax();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max);
    }
}

วิธีนี้สามารถให้ประสิทธิภาพที่ดีกว่าแบบวนรอบแบบคลาสสิกได้เนื่องจากsummaryStatisticsวิธีนี้เป็นการดำเนินการลดขนาดและช่วยให้สามารถทำการขนานได้


57

ห้องสมุด Google ฝรั่งมีนาทีและวิธีการสูงสุดในตัวอักษรของ Ints, Longs ฯลฯ เรียน

ดังนั้นคุณสามารถใช้:

Chars.min(myarray)

ไม่จำเป็นต้องมีการแปลงและมีการใช้งานอย่างมีประสิทธิภาพ


4
มันนำมาใช้มากหรือน้อยเช่นในคำถามยกเว้นว่ามันจะพ่น IllegalArgumentException สำหรับอาร์เรย์ของความยาว 0. ( code.google.com/p/guava-libraries/source/browse/trunk/src/com/... )
ColinD

3
นี่คือทางออกที่ดีที่สุดของทุกสิ่งที่นี่ หลีกเลี่ยง java.util.Arrays ทั้งหมดที่ # asList ทำให้เกิดความสับสน

20

ใช่เสร็จแล้วในคลาสCollections โปรดทราบว่าคุณจะต้องแปลงชุดอักขระดั้งเดิมเป็นอักขระ [] ด้วยตนเอง

ตัวอย่างสั้น ๆ :

import java.util.*;

public class Main {

    public static Character[] convert(char[] chars) {
        Character[] copy = new Character[chars.length];
        for(int i = 0; i < copy.length; i++) {
            copy[i] = Character.valueOf(chars[i]);
        }
        return copy;
    }

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};
        Character[] b = convert(a);
        System.out.println(Collections.max(Arrays.asList(b)));
    }
}

1
Collections.min (myCollection); หากคุณต้องการใช้สำหรับอาร์เรย์คุณสามารถทำได้เช่น Collections.min (Arrays.asList (myArray));
Zed

3
การแปลง a char []เป็นCharacter []เพียงการพิจารณาสูงสุดนั้นค่อนข้างไม่มีประสิทธิภาพ - ควรสร้างคลาสยูทิลิตี้ด้วยวิธีการคงที่สำหรับแต่ละประเภทดั้งเดิมที่คล้ายกับjava.util.Arrays: java.sun.com/javase/6/docs/api/java/util/Arrays.html
Christoph

@Christoph: ใช่ถ้าขนาดของอาร์เรย์มีขนาดใหญ่ฉันจะเห็นด้วย เพียงแค่ระบุว่า "ไม่มีประสิทธิภาพ" ไม่สมเหตุสมผลหากแอปพลิเคชันที่มีปัญหาทำให้การเรียกฐานข้อมูลและ / หรือการดำเนินการ I / O จำนวนมากและขนาดของอาร์เรย์มีขนาดเล็ก (สัมพันธ์กัน)
บาร์ต Kiers

คุณควรใช้Character.valueOf(chars[i])แทนnew Character(chars[i])เหตุผลด้านประสิทธิภาพ: java.sun.com/javase/6/docs/api/java/lang/…
Christoph

@Christoph Christoph ถูกต้องมันไม่มีประสิทธิภาพและโง่ที่จะแปลงอาเรย์เป็น Collection สำหรับการค้นหาขั้นต่ำสุด
AlexWien

16
import java.util.Arrays;

public class apples {

  public static void main(String[] args) {
    int a[] = {2,5,3,7,8};
    Arrays.sort(a);

     int min =a[0];
    System.out.println(min);
    int max= a[a.length-1];
    System.out.println(max);

  }

}

4
โปรดให้คำอธิบายบางอย่าง
Mike Stockdale

3
ฉันคิดว่าสิ่งนี้หมายความว่าถ้าคุณเรียงลำดับ (ตามลำดับจากน้อยไปมาก) ตามคำจำกัดความค่าต่ำสุดจะอยู่ที่ตำแหน่งแรกเสมอ [0] และค่าสูงสุดจะอยู่ที่ตำแหน่งสุดท้ายเสมอ , [a.length-1]
เจฟฟ์

1
นี่เป็นวิธีที่ถูกต้องและเป็นประโยชน์ในการแก้ปัญหา อะไรคือข้อเสียของการใช้มันเมื่อเทียบกับคนอื่น ๆ ?
อเล็กซ์

8
ความซับซ้อนของเวลา @alex - การเรียงลำดับเป็นเรื่อง O (nlogn) ที่ดีที่สุดในขณะที่วิธี Michael Rutherfurd คือ O (n)
jajdoo

3
เราไม่ต้องการเรียงลำดับเนื่องจากการวนซ้ำซ้ำในรายการก็เพียงพอที่จะค้นหาจำนวนนาทีและสูงสุด
akhil_mittal

11

ฉันมีชั้นผู้ช่วยเล็กน้อยในแอปพลิเคชันทั้งหมดของฉันด้วยวิธีการเช่น:

public static double arrayMax(double[] arr) {
    double max = Double.NEGATIVE_INFINITY;

    for(double cur: arr)
        max = Math.max(max, cur);

    return max;
}

1
คุณควรใช้ double max = DoubleNEGATIVE_INFINITY แทน double max = Double.MIN_VALUE; เนื่องจาก MIN_VALUE สำหรับ double เป็นค่าบวก
krems

1
... หรือคุณสามารถตั้งค่าสูงสุดเป็นรายการแรกในอาร์เรย์และทำซ้ำจากรายการที่ 2 ดูคำตอบของฉัน
นิโคลัสแฮมิลตัน

3

คุณสามารถทำได้อย่างง่ายดายด้วยIntStreamและmax()วิธีการ

ตัวอย่าง

public static int maxValue(final int[] intArray) {
  return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}

คำอธิบาย

  1. range(0, intArray.length)- intArrayเพื่อให้ได้กระแสที่มีองค์ประกอบเป็นจำนวนมากในปัจจุบัน

  2. map(i -> intArray[i])- intArrayแผนที่องค์ประกอบของสตรีทุกคนที่จะเป็นองค์ประกอบที่แท้จริงของ

  3. max()- OptionalIntรับองค์ประกอบสูงสุดของกระแสนี้เช่น

  4. getAsInt()- OptionalIntแกะ (คุณสามารถใช้ที่นี่: orElse(0)ในกรณีที่OptionalIntว่างเปล่า)



2
import java.util.Random;

public class Main {

public static void main(String[] args) {
   int a[] = new int [100];
   Random rnd = new Random ();

    for (int i = 0; i< a.length; i++) {
        a[i] = rnd.nextInt(99-0)+0;
        System.out.println(a[i]);
    }

    int max = 0;          

    for (int i = 0; i < a.length; i++) {
        a[i] = max;


        for (int j = i+1; j<a.length; j++) {
            if (a[j] > max) {
               max = a[j];
            }

        }
    }

    System.out.println("Max element: " + max);
}
}


2

วิธีแก้ปัญหาด้วยreduce():

int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);

// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97

ในโค้ดข้างต้นreduce()ส่งกลับข้อมูลในOptionalรูปแบบที่คุณสามารถแปลงไปโดยintgetAsInt()

หากเราต้องการเปรียบเทียบค่าสูงสุดกับจำนวนที่แน่นอนเราสามารถตั้งค่าเริ่มต้นในreduce():

int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100

ในรหัสด้านบนเมื่อreduce()มีการระบุตัวตน (ค่าเริ่มต้น) เป็นพารามิเตอร์แรกมันส่งกลับข้อมูลในรูปแบบเดียวกันกับตัวตน ด้วยคุณสมบัตินี้เราสามารถใช้วิธีนี้กับอาร์เรย์อื่น:

double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0

1

ตัวอย่างที่มีการลอย:

public static float getMaxFloat(float[] data) {

    float[] copy = Arrays.copyOf(data, data.length);
    Arrays.sort(copy);
    return copy[data.length - 1];
}

public static float getMinFloat(float[] data) {

    float[] copy = Arrays.copyOf(data, data.length);
    Arrays.sort(copy);
    return copy[0];
}

ในขณะที่โซลูชันของคุณใช้งานได้ แต่จะเพิ่มความซับซ้อนของเวลาเป็น O (nlogn) ในขณะที่ min สามารถพบได้ง่ายใน O (n) โดยใช้คำตอบอื่น ๆ
Pramod

ก็บ้าที่จะใช้การเรียงลำดับในสถานการณ์นี้
นิโคลัสแฮมิลตัน

มันจะมีประโยชน์เมื่อต้องการค่าน้อยที่สุด / มากที่สุด n> 1 พร้อมการซ่อมแซมบางอย่าง
biziclop

1

นี่คือวิธีการรับค่าสูงสุดในการทำงานประมาณ 99% (เปลี่ยน 0.01 เพื่อให้ได้ผลลัพธ์ที่ดีกว่า):

public static double getMax(double[] vals){
    final double[] max = {Double.NEGATIVE_INFINITY};

    IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
            .forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);

    return max[0];
}

(ไม่ร้ายแรงอย่างสมบูรณ์)


;-) นั่นคือ“ ไม่จริงจังอย่างสมบูรณ์” ไม่เป็นไร ลังเลที่จะถอนเงิน…
โอเล VV

0

ผ่านอาร์เรย์เป็นวิธีที่แปลก ๆ ด้วยArrays.sort()ดังนั้นจึงมีเพียงการเรียงลำดับอาร์เรย์วิธีการที่จะใช้แล้วชุดนาทีไปarray[0]และสูงสุดarray[array.length-1]ที่จะ


3
มันอาจจะคุ้มค่าที่จะสังเกตว่า a) สิ่งนี้จะปรับเปลี่ยนอาร์เรย์และ b) สำหรับอาร์เรย์ขนาดใหญ่มันเป็นทางออกที่แพงกว่า O (nlog n) มากกว่า O (n)
davidsheldon

0

วิธีพื้นฐานในการรับค่าต่ำสุด / สูงสุดของ Array หากคุณต้องการอาเรย์ที่ไม่เรียงลำดับคุณสามารถสร้างสำเนาหรือส่งไปยังเมธอดที่ส่งคืนค่า min หรือ max ถ้าไม่เรียงลำดับจะดีกว่าเพราะมันทำงานได้เร็วขึ้นในบางกรณี

public class MinMaxValueOfArray {
    public static void main(String[] args) {
        int[] A = {2, 4, 3, 5, 5};
        Arrays.sort(A);
        int min = A[0];
        int max = A[A.length -1];
        System.out.println("Min Value = " + min);        
        System.out.println("Max Value = " + max);
    }
}

2
ปัญหาเกี่ยวกับการเรียงลำดับคือมีค่าใช้จ่าย O (n log n) สำหรับปัญหา O (n) แต่นี่จะดีกว่าคำตอบ "เรียงลำดับแถวลำดับ" สามแบบที่ได้ให้ไปแล้ว
Teepeemm
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.