जावा फंक और एक्शन के समकक्ष हैं


86

जावा फंक और एक्शन के समकक्ष क्या हैं ?

मेरा मतलब है, अपने दम पर यह लिखने के बजाय:

public interface Func<TInput, TResult>
{
    TResult call(TInput target) throws Exception;
}
public interface Action<T>
{
    void call(T target) throws Exception;
}

इसके अलावा stackoverflow.com/questions/7296606/…
nawfal

जवाबों:


96

जावा 8 में, समतुल्य क्रमशः java.util.function.Function<T, R>और java.util.function.Consumer<T>इंटरफेस हैं। इसी तरह, java.util.function.Predicate<T>के बराबर है System.Predicate<T>। जैसा कि कहीं और उल्लेख किया गया है, ये प्रतिनिधियों के बजाय इंटरफेस हैं।

अलग से संबंधित: मैं वर्तमान में LINQ की तरह विस्तार विधि सामान करने के लिए निम्न उपयोगिता वर्ग पर बहुत अधिक झुकाव कर रहा हूं:

abstract class IterableUtil {
  public static <T> Iterable<T> where(Iterable<T> items, Predicate<T> predicate) {
    ArrayList<T> result = new ArrayList<T>();
    for (T item : items) {
      if (predicate.test(item)) {
        result.add(item);
      }
    }
    return result;
  }

  public static <T, R> Iterable<R> select(Iterable<T> items, Function<T, R> func) {
    ArrayList<R> result = new ArrayList<R>();
    for (T item : items) {
      result.add(func.apply(item));
    }
    return result;
  }
}

इसके विपरीत System.Linq.Enumerable.Where<TSource>और System.Linq.Enumerable.Select<TSource, TResult>मेरे द्वारा प्रस्तुत LINQ- जैसी विधियां आलसी नहीं हैं और कॉलर को परिणाम संग्रह वापस करने से पहले स्रोत संग्रह को पूरी तरह से पार कर लेते हैं। फिर भी, मैं उन्हें विशुद्ध रूप से वाक्यात्मक उद्देश्यों के लिए उपयोगी पाता हूं और यदि आवश्यक हो तो आलसी बनाया जा सकता है। दिया हुआ

class Widget {
  public String name() { /* ... */ }
}

एक निम्नलिखित कर सकते हैं:

List<Widget> widgets = /* ... */;
Iterable<Widget> filteredWidgets = IterableUtil.where(widgets, w -> w.name().startsWith("some-prefix"));

जिसे मैं निम्नलिखित पसंद करता हूं:

List<Widget> widgets = /* ... */;
List<Widget> filteredWidgets = new ArrayList<Widget>();
for (Widget w : widgets) {
  if (w.name().startsWith("some-prefix")) {
    filteredWidgets.add(w);
  }
}

1
हमें वास्तव में इस जवाब को वोट करने की आवश्यकता है क्योंकि यह प्रश्न "जावा समकक्ष की कार्रवाई" के लिए वर्तमान # 1 खोज परिणाम है और यह अब 2015 है इसलिए जावा 8 सामान जावा से पहले और लगभग mimics .net के सामान की तुलना में बेहतर है। बिंदु।
रॉबर्ट सी। बर्थ

1
मुझे लगता है कि आप Iterable <Widget> filteredWidgets = IterableUtil.where (विगेट्स, डब्ल्यू -> w.name () शुरू करते हैं। (कुछ-कुछ उपसर्ग ") के साथ;
विद्युत्बाहु

1
के अलावा Function<T, R>और Consumer<T>, आप सामान्य कार्यात्मक इंटरफेस का पूरा सेट है कि जावा प्रदान करता है पा सकते हैं यहाँ
जैम्स

35

कॉल करने योग्य इंटरफ़ेस फ़ंक के समान है।

रनने योग्य इंटरफ़ेस एक्शन के समान है।

सामान्य तौर पर, जावा सी # प्रतिनिधियों के प्रतिस्थापन के रूप में अनाम आंतरिक कक्षाओं का उपयोग करता है। उदाहरण के लिए यह है कि आप GUI में बटन प्रेस पर प्रतिक्रिया करने के लिए कोड कैसे जोड़ते हैं:

button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) { 
          ...//code that reacts to the action... 
      }
});

13
Func को Callable से अलग करता है, यह है कि 16 तर्कों (Func <TResult>, Func <T, TResult>, Func <T1, T2, TResult>, आदि) के लिए सामान्य अधिभार हैं। OTOH, Callable कोई तर्क नहीं लेता है। इसके अलावा, जेनेरिक में प्रकार के क्षरण के कारण C # के ओवरलोड को लागू करना असंभव है।
एलेक्ट्रा डबलिनस्की

6

अतिभारित समारोह प्रतिनिधियों (डेलीगेट बनाम गुमनाम वर्ग मुद्दे के अलावा) की शान है कि वे 0 से 16 तर्क से समर्थन है ( Func<TResult>, Func<T, TResult>, Func<T1, T2, TResult>, आदि)

दुर्भाग्य से, प्रकार के क्षरण के कारण जावा में यह असंभव है। कक्षाएं केवल सामान्य प्रकार के मापदंडों से भिन्न नहीं हो सकती हैं।

जावा 8 अब जैसे नामों के एक चिड़ियाघर में लाता है BiConsumerके लिए Action<T, T2>, और, क्योंकि जावा आदिम प्रकार तर्क की अनुमति नहीं है BiIntConsumer। "चिड़ियाघर", हालांकि, बहुत बड़ा नहीं है, और मुझे एक पुस्तकालय के बारे में पता नहीं है जो इसे विस्तारित करता है। फ़ंक्शन प्रकार के शाब्दिक जैसे एक अद्भुत प्रस्ताव (int, int) => voidथा लेकिन इसे अपनाया नहीं गया था।


3
दिलचस्प बात यह है कि सीएलआर स्तर की कक्षाओं में जो केवल जेनेरिक मापदंडों की संख्या से भिन्न होते हैं उनके अलग-अलग नाम होते हैं। Func`1आदि। यह सिर्फ C # है जो उन लोगों को समान नाम देता है।
कोडइन्चोस

@CodesInChaos आह, बहुत दिलचस्प है। बहुत बुरा जावा ने इसे इस तरह से भी नहीं किया। Btw, जावा 8 अब जैसे नामों के एक चिड़ियाघर में लाता है BiConsumerके लिए Action<T, T2>, और, क्योंकि जावा आदिम प्रकार पैरामीटर की अनुमति नहीं है BiIntConsumer। फ़ंक्शन प्रकार के शाब्दिक जैसे प्रस्ताव था, (int, int) => voidलेकिन इसे अपनाया नहीं गया था।
अलेक्सांद्र डबिन्सकी

5

Func<T>उपयोग के लिए: java.util.function.Supplier http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html


SupplierFunc<T>(के विपरीत Func<T1, T2>) के बराबर होगा Action। एक Actionकोई तर्क स्वीकार करता है और कोई परिणाम देता है। (अन्य संस्करण Actionविभिन्न तर्कों को स्वीकार करते हैं और कोई परिणाम नहीं देते हैं।)
20

हां तुम सही हो, मेरी गलती है। मैं इस पोस्ट में भाग गया क्योंकि मैं Func<T>जावा की तलाश कर रहा था और गलती से इसे याद कर लिया था Action<T>। उफ़
टिम Schruben

जवाब मेरे लिए वैसे भी मददगार था। क्या जावा में भी कुछ ऐसा है Action<>: 0 इनपुट, 0 आउटपुट। .andThen(...)कार्यक्षमता के साथ सबसे अच्छा ।
कोल्या इवानकोव

मुझे जावा फ्रेमवर्क द्वारा प्रदान की गई किसी भी चीज़ के बारे में पता नहीं है जो Action<>0 इनपुट और 0 आउटपुट के साथ है। लेकिन रीमर्बर, जावा में ये सिर्फ इंटरफेस हैं। तो, आप अपने खुद के उपयोग करने के लिए बना सकते हैं।
टिम श्रुबेन

नहीं है Runnableके लिए Action<>, हालांकि यह काफी के रूप में बहुत नया जावा 8 कार्यात्मक सामान के रूप में उपयोग करने के लिए नहीं है,।
मार्क के कोवान

3

वास्तव में उन लोगों के लिए कोई समकक्ष नहीं हैं। आप जावा में अनाम आंतरिक कक्षाएं बना सकते हैं, लेकिन फ़ंक और एक्शन जैसे सामान्य लोगों के बजाय विशिष्ट इंटरफेस हो सकते हैं।


3

जावा में प्रतिनिधियों की अवधारणा नहीं है। वर्कअराउंड अप्रोच के लिए, कृपया C # डेलीगेट्स पर एक जावा प्रोग्रामर लुक्स देखें :

जबकि C # में जावा के समान क्षमताओं का एक सेट है, इसने कई नई और दिलचस्प विशेषताएं जोड़ी हैं। प्रतिनिधिमंडल एक विधि को प्रथम श्रेणी की वस्तु के रूप में मानने की क्षमता है। एसी # डेलीगेट का उपयोग किया जाता है जहां जावा डेवलपर्स एक एकल विधि के साथ एक इंटरफेस का उपयोग करेंगे। इस लेख में, C # में प्रतिनिधियों के उपयोग पर चर्चा की गई है, और जावा डेलीगेट ऑब्जेक्ट के लिए कोड प्रस्तुत किया गया है जो एक समान कार्य कर सकता है। यहां सोर्स कोड डाउनलोड करें।


3

आप java.util का उपयोग कर सकते हैं। इस तरह से

Function<Employee, String> f0 = (e) -> e.toString();

लेकिन अगर आप इसे एक से अधिक तर्क के साथ उपयोग कर रहे हैं (जैसा कि C # Func है), तो आपने अपने संस्करण का कार्य FunctionalInterface के रूप में परिभाषित किया है।

@FunctionalInterface
public interface Func2Args<T, T1, R> {
    R apply(T t, T1 t1);
}

@FunctionalInterface
public interface Func3Args<T,T1,T2,R> {
    R apply(T t, T1 t1, T2 t2);
}

तब आप चर के साथ उपयोग कर सकते हैं तर्कों के नहीं

Func2Args<Employee,Employee,String> f2 = (e, e2) -> e.toString() + 
e2.toString();

Func3Args<Employee,Employee,Employee,String> f3 = (e, e2, e3) -> 
e.toString() + e2.toString() + e3.toString();

1

Java 8 से पुराने संस्करणों के लिए

C # में विधि कॉलबैक के लिए जिसका मैंने इस तरह उपयोग किया:

public void MyMethod(string par1, string par2, Action<int> callback, Action<int, string> callback2)
{
    //Async Code 
        callback.invoke(1);
        callback2.invoke(4, "str");
}

और इसे कॉल करना:

utils.MyMethod("par1", "par2", (i) =>
{
    //cb result
}, (i, str) =>
{
    //cb2 result
});

मैंने जावा में छोटे अमूर्त वर्ग बनाए हैं

package com.example.app.callbacks;
public abstract class Callback1<T> {
    public void invoke(T obj) {}
}

package com.example.app.callbacks;
public abstract class Callback2<T, T2> {
    public void invoke(T obj, T2 obj2) {}
}

package com.example.app.callbacks;
public abstract class Callback3<T, T2, T3> {
    public void invoke(T obj, T2 obj2, T3 obj3) {}
}

...ETC

जावा विधि की तरह दिखता है:

public void myMethod(String par1, String par2, final Callback1<int> callback, final Callback2<int, String> callback2) {
    //Async Code 
        callback.invoke(1);
        callback2.invoke(4, "str");
}

अब इसे जावा में कॉल करते समय:

utils.myMethod("par1", "par2", new Callback<int>() {
    @Override
    public void invoke(int obj) {
        super.invoke(obj);
        //cb result
    }
}, new Callback2<int, String>() {
    @Override
    public void invoke(int obj, String obj2) {
        super.invoke(obj, obj2);
        //cb2 result
    }
});

यह आपके कॉलबैक को उन कक्षाओं में पास / सेट करके भी काम करता है, जिनमें आप उन्हें कॉल करना चाहते हैं, उसी तरीके का उपयोग इंटरफेसेस बनाने के लिए भी किया जा सकता है:

package com.example.app.interfaces;
public interface MyInterface<T> {
    void makeDo(T obj);
    void makeAnotherDo();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.