วิธีรับค่าสูงสุดจาก Collection (ตัวอย่างเช่น ArrayList)


138

มี ArrayList ที่เก็บค่าจำนวนเต็ม ฉันต้องการค้นหาค่าสูงสุดในรายการนี้ เช่นสมมติว่า arrayList ค่าที่เก็บไว้คือ: และค่าสูงสุดจะเป็น10, 20, 30, 40, 5050

วิธีที่มีประสิทธิภาพในการหาค่าสูงสุดคืออะไร?

@ แก้ไข:ฉันเพิ่งพบวิธีแก้ปัญหาหนึ่งที่ฉันไม่แน่ใจมาก

ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(100); /* add(200), add(250) add(350) add(150) add(450)*/

Integer i = Collections.max(arrayList)

และส่งคืนค่าสูงสุด

อีกวิธีหนึ่งในการเปรียบเทียบค่าแต่ละค่าเช่น selection sort or binary sort algorithm  


2
คุณพยายามหาค่าหรือไม่? ติดขัดตรงไหน โซลูชันของคุณเองอาจไม่มีประสิทธิภาพเกินไปหรือไม่?
Anthony Pegram

1
หากเป็นสิ่งที่คุณทำ Java จำนวนมากจะรวบรวมเข้ากับแอสเซมบลีเว้นแต่คุณจะทำอะไรโง่ ๆ โค้ดของคุณจะค่อนข้างมีประสิทธิภาพด้วยการทำซ้ำง่ายๆ
Bill K

@AnthonyPegram: ฉันหมายถึงอัลกอริทึมการเรียงลำดับใดหรือมีวิธีใดใน java? BTW ตรวจสอบคำตอบของ gotomanners
user1010399

สำหรับอาร์เรย์ที่อาจมีnullค่า: stackoverflow.com/questions/369383/…
Ciro Santilli 郝海东冠状病六四事件法轮功

คำตอบ:


298

คุณสามารถใช้Collections APIเพื่อบรรลุสิ่งที่คุณต้องการได้อย่างง่ายดาย - อ่านอย่างมีประสิทธิภาพ - Javadocเพียงพอ สำหรับ Collections.max

Collections.max(arrayList);

ส่งคืนองค์ประกอบสูงสุดของคอลเล็กชันที่กำหนดตามลำดับองค์ประกอบตามธรรมชาติ องค์ประกอบทั้งหมดในคอลเลกชันต้องใช้อินเทอร์เฟซที่เปรียบเทียบได้


10
เหตุใดจึงเป็นคำตอบที่ได้รับการยอมรับ มันไม่ได้แก้ปัญหาที่มีประสิทธิภาพมากที่สุด กรณีที่ดีที่สุดคือ O (n log (n)) และเลือกสูงสุดโดยการตรวจสอบทั้งหมดคือ O (n) เท่านั้น
Brendan Long

1
ใช่การทำซ้ำในรายการO(n log(n))แต่ถ้า "ไม่มีวิธีใดที่มีประสิทธิภาพเป็นพิเศษ" คุณเสนอว่าอะไรเป็นวิธีแก้ปัญหาที่ดีกว่านอกจากการตรวจสอบทั้งหมด
gotomanners

การทำซ้ำอย่างไร้เดียงสานั้นเร็วกว่า (ตรวจสอบแล้วตัวเปรียบเทียบกำลังดึงคะแนนจากแผนที่) มากกว่าการเรียงลำดับและรับองค์ประกอบแรกหรือใช้สูงสุด ทั้ง sort + take ก่อนและ max ใช้ lambda
majTheHero

32

คำถามนี้เกือบหนึ่งปีแล้ว แต่ฉันพบว่าถ้าคุณสร้างตัวเปรียบเทียบแบบกำหนดเองสำหรับอ็อบเจ็กต์คุณสามารถใช้ Collections.max สำหรับรายการอาร์เรย์ของวัตถุ

import java.util.Comparator;

public class compPopulation implements Comparator<Country> {
    public int compare(Country a, Country b) {
        if (a.getPopulation() > b.getPopulation())
            return -1; // highest value first
        if (a.getPopulation() == b.Population())
            return 0;
        return 1;
    }
}
ArrayList<Country> X = new ArrayList<Country>();
// create some country objects and put in the list
Country ZZ = Collections.max(X, new compPopulation());

คุณต้องการตัวเปรียบเทียบแบบกำหนดเองสำหรับประเภทปฏิทินหรือไม่?
tatmanblue

รหัสของคุณส่งคืนค่าที่น้อยที่สุดในรายการถ้า (a.getPopulation ()> b.getPopulation ()) ส่งกลับ -1; ข้างต้นต้องเปลี่ยนเป็น if (a.getPopulation () <b.getPopulation ()) return -1; // ค่าสูงสุดอันดับแรก
Chandrakanth Gowda

ซึ่งสามารถทำได้โดยใช้ lambda เช่นกัน: maxElement = Collections.max (collection, (el1, el2) -> el1 - el2);
majTheHero

22
public int getMax(ArrayList list){
    int max = Integer.MIN_VALUE;
    for(int i=0; i<list.size(); i++){
        if(list.get(i) > max){
            max = list.get(i);
        }
    }
    return max;
}

จากความเข้าใจของฉันนี่คือสิ่งที่ Collections.max () ทำโดยทั่วไปแม้ว่าจะใช้ตัวเปรียบเทียบเนื่องจากรายการเป็นแบบทั่วไป


นี่เร็วกว่าสิ่งอื่นใดสำหรับกรณีของฉัน
majTheHero

14

เราสามารถใช้Collections.max()และCollections.min()วิธีการ

public class MaxList {
    public static void main(String[] args) {
        List l = new ArrayList();
        l.add(1);
        l.add(2);
        l.add(3);
        l.add(4);
        l.add(5);
        System.out.println(Collections.max(l)); // 5
        System.out.println(Collections.min(l)); // 1
    }
}

9

คลาสจำนวนเต็มใช้เทียบเคียงได้ดังนั้นเราสามารถรับค่าสูงสุดหรือต่ำสุดของรายการจำนวนเต็มได้อย่างง่ายดาย

public int maxOfNumList() {
    List<Integer> numList = new ArrayList<>();
    numList.add(1);
    numList.add(10);
    return Collections.max(numList);
}

หากคลาสไม่ได้ใช้การเปรียบเทียบและเราต้องหาค่าสูงสุดและต่ำสุดเราจะต้องเขียนตัวเปรียบเทียบของเราเอง

List<MyObject> objList = new ArrayList<MyObject>();
objList.add(object1);
objList.add(object2);
objList.add(object3);
MyObject maxObject = Collections.max(objList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        if (o1.getValue() == o2.getValue()) {
            return 0;
        } else if (o1.getValue() > o2.getValue()) {
            return -1;
        } else if (o1.getValue() < o2.getValue()) {
            return 1;
        }
        return 0;
    }
});

7

Comparator.comparing

ใน Java 8 คอลเลกชันได้รับการปรับปรุงโดยใช้แลมด้า ดังนั้นการค้นหาสูงสุดและต่ำสุดสามารถทำได้ดังนี้โดยใช้Comparator.comparing:

รหัส:

List<Integer> ints = Stream.of(12, 72, 54, 83, 51).collect(Collectors.toList());
System.out.println("the list: ");
ints.forEach((i) -> {
    System.out.print(i + " ");
});
System.out.println("");
Integer minNumber = ints.stream()
        .min(Comparator.comparing(i -> i)).get();
Integer maxNumber = ints.stream()
        .max(Comparator.comparing(i -> i)).get();

System.out.println("Min number is " + minNumber);
System.out.println("Max number is " + maxNumber);

เอาท์พุต:

 the list: 12 72 54 83 51  
 Min number is 12 
 Max number is 83

5

ไม่มีวิธีใดที่มีประสิทธิภาพโดยเฉพาะอย่างยิ่งในการค้นหาค่าสูงสุดในรายการที่ไม่ได้เรียงลำดับคุณเพียงแค่ต้องตรวจสอบทั้งหมดและส่งคืนค่าสูงสุด


จำนวนเต็มนี้i = Collections.max(arrayList)ล่ะ มันส่งคืนค่าสูงสุดในกรณีของฉันไม่ว่าฉันจะไม่แน่ใจมากนัก คุณพูดอะไร?
user1010399

@ user1010399 - นี่คือสิ่งที่ฉันพูด - มันตรวจสอบทุกค่าและส่งกลับค่าสูงสุด
Brendan Long

โอเคไม่เป็นไร ขอบคุณ. ฉันสับสนเล็กน้อยระหว่างวิธีการรวบรวมและอัลกอริทึมการเรียงลำดับนี้
user1010399

4

ต่อไปนี้เป็นอีกสามวิธีในการค้นหาค่าสูงสุดในรายการโดยใช้สตรีม:

List<Integer> nums = Arrays.asList(-1, 2, 1, 7, 3);
Optional<Integer> max1 = nums.stream().reduce(Integer::max);
Optional<Integer> max2 = nums.stream().max(Comparator.naturalOrder());
OptionalInt max3 = nums.stream().mapToInt(p->p).max();
System.out.println("max1: " + max1.get() + ", max2: " 
   + max2.get() + ", max3: " + max3.getAsInt());

วิธีการเหล่านี้ทั้งหมดเช่นเดียวกับการCollections.maxทำซ้ำในคอลเลคชันทั้งหมดดังนั้นจึงต้องใช้เวลาตามสัดส่วนกับขนาดของคอลเล็กชัน


3

จาวา 8

เนื่องจากจำนวนเต็มสามารถเทียบเคียงได้เราสามารถใช้หนึ่งซับต่อไปนี้ใน:

List<Integer> ints = Stream.of(22,44,11,66,33,55).collect(Collectors.toList());
Integer max = ints.stream().mapToInt(i->i).max().orElseThrow(NoSuchElementException::new); //66
Integer min = ints.stream().mapToInt(i->i).min().orElseThrow(NoSuchElementException::new); //11

จุดที่จะต้องทราบก็คือเราไม่สามารถใช้Funtion.identity()ในสถานที่ของi->iเป็นmapToIntคาดซึ่งเป็นอินเตอร์เฟซที่แตกต่างกันอย่างสมบูรณ์และไม่เกี่ยวข้องกับToIntFunction Functionยิ่งไปกว่านั้นอินเทอร์เฟซนี้มีเพียงวิธีเดียวapplyAsIntและไม่มีidentity()วิธีการ



1

นี่คือ fucntion

public int getIndexOfMax(ArrayList<Integer> arr){
    int MaxVal = arr.get(0); // take first as MaxVal
    int indexOfMax = -1; //returns -1 if all elements are equal
    for (int i = 0; i < arr.size(); i++) {
        //if current is less then MaxVal
        if(arr.get(i) < MaxVal ){
            MaxVal = arr.get(i); // put it in MaxVal
            indexOfMax = i; // put index of current Max
        }
    }
    return indexOfMax;  
}

1
package in.co.largestinarraylist;

import java.util.ArrayList;
import java.util.Scanner;

public class LargestInArrayList {

    public static void main(String[] args) {

        int n;
        ArrayList<Integer> L = new ArrayList<Integer>();
        int max;
        Scanner in = new Scanner(System.in);
        System.out.println("Enter Size of Array List");
        n = in.nextInt();
        System.out.println("Enter elements in Array List");

        for (int i = 0; i < n; i++) {
            L.add(in.nextInt());
        }

        max = L.get(0);

        for (int i = 0; i < L.size(); i++) {
            if (L.get(i) > max) {
                max = L.get(i);
            }
        }

        System.out.println("Max Element: " + max);
        in.close();
    }
}

1

นอกเหนือจากคำตอบของ gotomannersแล้วในกรณีที่มีคนอื่นมาที่นี่เพื่อค้นหาวิธีแก้ปัญหาที่ปลอดภัยเป็นโมฆะสำหรับปัญหาเดียวกันนี่คือสิ่งที่ฉันลงเอยด้วย

Collections.max(arrayList, Comparator.nullsFirst(Comparator.naturalOrder()))


-3

ขึ้นอยู่กับขนาดของอาร์เรย์ของคุณโซลูชันแบบมัลติเธรดอาจเร่งความเร็วได้เช่นกัน


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