2013-02-23 34 views
5

Math.max का कार्यान्वयन क्यों नहीं है variadic function?मैथ.मैक्स क्यों नहीं है (डबल ए, डबल बी) varadic?

यह इस तरह से कार्यान्वित हो सकता है:

public class Main { 
    public static double max(double... values) { 
     double max = Double.NEGATIVE_INFINITY; 
     for (double tmp : values) { 
      max = max < tmp ? tmp : max; 
     } 
     return max; 
    } 

    public static void main(String[] args) { 
     // This works fine: 
     System.out.println(max(-13, 12, 1337, 9)); 

     // This doesn't work: 
     // System.out.println(Math.max(-13, 12, 1337)); 
    } 
} 

वहाँ किसी भी कारण है कि इसे इस तरह लागू नहीं किया गया है?

+4

मठ जावा 1.0 में पेश किया गया था। 1.5 में Varargs ... – Kai

उत्तर

3

जबकि अन्य ने पहले से ही जवाब दिया है कि क्यों Math.max भिन्न नहीं है, उन्होंने जवाब नहीं दिया कि इस तरह की विधि क्यों नहीं बनाई जाती है जब विविध कार्य शुरू किए जाते हैं।

मैं भी यह पता नहीं (वहाँ है एक open bug-report) तो मैं केवल अनुमान लगा सकते हैं:

यह सच है कि यह Math में लागू नहीं किया गया है, लेकिन अगर हम Collections पर गौर निम्न विधि है:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll) { 
    ... 
} 

प्रकार हस्ताक्षर बदसूरत लग रहा है (यह काफी लचीला सहप्रसरण और contravariance संभाल करने की जरूरत है), यह आसानी से, Collections.max(Arrays.asList(-13, 12, 1337, 9)); साथ इस्तेमाल किया जा सकता सभी कार्य कार्यान्वित किया जाता है के बाद सिर्फ एक अलग जगह में।

इससे भी बेहतर: यह विधि न केवल युगल को संभाल सकती है, लेकिन Comparable इंटरफ़ेस को लागू करने वाले सभी प्रकार।

फिर भी न तो आपके सुझाए गए समाधान, और न ही Collections में समाधान ऑब्जेक्ट उन्मुख है, वे केवल स्थिर तरीके हैं। JDK8 साथ सौभाग्य से इस बदल जाएगा:

import java.util.Arrays; 
import java.util.List; 
import java.util.Optional; 

int max(List<Integer> list) { 
    Optional<Integer> opt = list.stream().max((a,b) -> a-b); 
    return opt.orElse(Integer.MAX_VALUE); 
} 

max(Arrays.asList(-13, 12, 1337, 9)); // 1337 
max(Arrays.asList()); // 2147483647 

आगामी रिलीज संग्रह पुस्तकालय Project Lambda में फिर से काम कर रहा है और अधिक वस्तु उन्मुख होने के लिए। उपर्युक्त उदाहरण में, अधिकतम तत्व निर्धारित करने के लिए लैम्ब्डास का उपयोग आसान और पठनीय तरीका प्रदान करने के लिए किया जाता है। निम्नलिखित भी काम करेगा:

Arrays.asList(-13, 12, 1337, 9) 
    .stream() 
    .reduce((a,b) -> a > b ? a : b) 
    .ifPresent(System.out::println); // 1337 

एक और विस्तार Optional का प्रयोग होता है:

import static java.util.Comparators.naturalOrder; 

Arrays.asList(-13, 12, 1337, 9) 
    .stream() 
    .max(naturalOrder()) 
    .ifPresent(System.out::println); // 1337 

के बजाय max एक भी उच्च आदेश समारोह reduce इस्तेमाल कर सकते हैं। ऊपर दिए गए उदाहरणों में दिखाए गए अनुसार उच्च आदेश कार्यों की संरचना के कारण त्रुटि प्रबंधन को सरल बनाने के लिए यह एक प्रकार है।

  1. यह वस्तु उन्मुख है
  2. यह बहुरूपी है:

    लैम्ब्डा प्रस्ताव के कई फायदे है कि यह अनावश्यक Math.max के variadic प्रपत्र लागू करने के लिए बनाने के है। इसका मतलब यह है कि यह संग्रह (List, Set, Stream, Iterator आदि)

  3. यह अर्थपूर्ण और समझने के लिए
  4. आसान है की हर प्रकार यह ऑन-द-मक्खी बनता है की अनुमति देता है के साथ प्रयोग किया जा सकता है। बस .parallelStream()
2

क्योंकि यह जावा में भिन्नता से अधिक लंबे समय तक मौजूद है (java 5 में पेश किया गया) और इसके बाद से इसे अपडेट करने की बहुत अधिक मांग नहीं थी, जैसा आपने अभी दिखाया है, स्वयं को करने के लिए यह छोटा है।

भी, वहाँ के ahidden प्रदर्शन दंड एक सरणी के रूप में varargs तरीकों में शामिल (डबल []) अपने तर्क से दृश्यों

+0

क्या आप जानते हैं कि जावा किस संस्करण के साथ विविध कार्य करता है? एक और सवाल: जावा कैसे तय करता है कि अधिकतम अधिकतम (डबल ... मान) 'और' अधिकतम (डबल ए, डबल बी) 'कौन सा फ़ंक्शन लेना चाहिए? मैंने कोशिश की है और यह गैर-भिन्नता लेता है, लेकिन मुझे इसे जेएलएस में नहीं मिला। –

+0

@moose - जावा 5 (मैंने एक लिंक शामिल किया है)। साथ ही, जैसा कि दासब्लिंकलाइट ने कहा कि वैरगा विधियां वास्तव में वे विधियां हैं जो इस मामले में एक सरणी - डबल [] स्वीकार करती हैं, इसलिए केवल 2 तर्कों के लिए गैर-vararg विधि एक बेहतर मिलान है। – radai

5

java.lang.Math JDK 1.0 में शुरू किया गया है के पीछे बनाया जाएगा, लंबे variadic कार्यों से पहले जावा 5 में भाषा में पेश किए गए थे।

इसके अतिरिक्त, दक्षता एक चिंता है: यदि आपको अधिकतर समय में दो तत्वों की आवश्यकता होती है, तो उन्हें "इनलाइन" पास करने के लिए बहुत तेज है, बिना किसी इंटरमीडिएट सरणी को बनाए रखने के लिए । यह कार्यान्वयन के अंदर एक लूप स्थापित करने की लागत से बचाता है। वापस JDK 1.0

0

Math.max() तारीख, जबकि variadic कार्यों से ही अस्तित्व में नहीं है जब तक जावा 5.

1

Math.max JDK 1.0 के बाद से आसपास किया गया है, लंबे समय से पहले तर्क वाक्य रचना की चर # पेश किया गया था। यह कहना नहीं है कि विधि को आपके द्वारा सुझाए जाने वाले तरीके को अपडेट नहीं किया जा सका। कभी-कभी लाइब्रेरी विधि परिभाषाएं या कार्यान्वयन बदल जाते हैं, लेकिन यह दुर्लभ है। मौजूदा तरीकों को संशोधित करने के बजाए अधिकांश समय कक्षाओं में नए तरीकों को जोड़ा जाता है।

मैक्स का आपका नया कार्यान्वयन वास्तव में विधि अधिभार का एक मामला है क्योंकि मौजूदा विधि और नए var args विधि एक ही कक्षा में मौजूद होने के लिए संभव है। इसलिए जब यह निश्चित रूप से मौजूदा विधि को प्रतिस्थापित कर सकता है, यह भी गणित वर्ग के लिए एक जोड़ा हो सकता है। तो मुझे लगता है कि इसे जोड़ा जाना चाहिए। तथ्य यह है कि हम मौजूदा विधि को अकेले छोड़ सकते हैं, नए कार्यान्वयन के प्रदर्शन के बारे में किसी भी चिंता को हटा देता है।

जावा एन और जावा एन + 1 के बीच क्या बदल सकता है की संस्कृति वैसे भी बदल रही है। उदाहरण के लिए, फ़ाइल एक्सेस क्लासेस और java.sql.Connection जावा 6 से जावा 7 में बदल दिए गए थे क्योंकि जावा 7 में वे अब AutoCloseable लागू करते हैं। जावा 9 वास्तव में project jigsaw के रास्ते में कक्षाओं से कुछ तरीकों को हटाने जा रहा है।

मैं Math.max को अद्यतन नहीं होने के लिए कोई वैध कारण नहीं सोच सकता। शायद अब तक कोई भी इसका सुझाव नहीं दे रहा है। क्या आप इसे पढ़ रहे हैं, Mark Reinhold?

2

जावा 8 करने के लिए .stream() बदलने धाराओं के साथ नंबर आपरेशन लागू किया गया है, जो बहुत लचीला है। एक उदाहरण:

DoubleStream.of(-13, 12, 1337, 9).max().getAsDouble() 

होमब्री के रूप में उतना आसान नहीं है, लेकिन अभी भी सीधे आगे, तेज़ और अधिक लचीला है।

उदाहरण के लिए, मल्टी कोर का इस्तेमाल कर रही जरूरत सिर्फ एक समारोह कॉल:

stream.parallel().max().getAsDouble() 

काफी, इस मामले में व्यर्थ है क्योंकि अधिकतम खोजने भी डबल के साथ बहुत तेजी से है - आप डबल्स के लाखों लोगों की जरूरत है एक को देखने के लिए मिलीसेकंड का अंतर। लेकिन अगर अन्य प्रसंस्करण हो तो यह जल्दी से उन्हें तेज कर सकता है।

या आप भी मिनट, औसत, योग आदि सभी एक ही बार में पा सकते हैं, बस प्रणाली वर्गों का उपयोग करना:

DoubleSummaryStatistics stat = DoubleStream.of(-13, 12, 1337, 9).summaryStatistics(); 
System.out.println(stat.getMin()); 
System.out.println(stat.getAverage()); 
System.out.println(stat.getMax()); 
System.out.println(stat.getCount()); 
System.out.println(stat.getSum());