ল্যাম্বডা এক্সপ্রেশন দিয়ে কীভাবে স্ট্রিম ()। মানচিত্র (…) ডিবাগ করবেন?


114

আমাদের প্রকল্পে আমরা জাভা 8 এ স্থানান্তরিত হচ্ছি এবং আমরা এর নতুন বৈশিষ্ট্যগুলি পরীক্ষা করছি।

আমার প্রকল্প আমি পেয়ারা predicates এবং ফাংশন ব্যবহার করছি ফিল্টার করুন এবং ব্যবহার করে কিছু সংগ্রহ রুপান্তর Collections2.transformএবং Collections2.filter

এই মাইগ্রেশনটিতে আমার উদাহরণস্বরূপ পেয়ারা কোডটি জাভাতে 8 পরিবর্তন করতে হবে। সুতরাং, আমি যে পরিবর্তনগুলি করছি তা হ'ল ধরণের:

List<Integer> naturals = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10,11,12,13);

Function <Integer, Integer> duplicate = new Function<Integer, Integer>(){
    @Override
    public Integer apply(Integer n)
    {
        return n * 2;
    }
};

Collection result = Collections2.transform(naturals, duplicate);

প্রতি...

List<Integer> result2 = naturals.stream()
    .map(n -> n * 2)
    .collect(Collectors.toList());

পেয়ারা ব্যবহার করে আমি কোডটি খুব ধরণের ডিবাগিং করছিলাম যেহেতু আমি প্রতিটি রূপান্তর প্রক্রিয়াটি ডিবাগ করতে পারি তবে আমার উদ্বেগ উদাহরণস্বরূপ কীভাবে ডিবাগ করা যায় .map(n -> n*2)

ডিবাগার ব্যবহার করে আমি কিছু কোড দেখতে পাচ্ছি:

@Hidden
@DontInline
/** Interpretively invoke this form on the given arguments. */
Object interpretWithArguments(Object... argumentValues) throws Throwable {
    if (TRACE_INTERPRETER)
        return interpretWithArgumentsTracing(argumentValues);
    checkInvocationCounter();
    assert(arityCheck(argumentValues));
    Object[] values = Arrays.copyOf(argumentValues, names.length);
    for (int i = argumentValues.length; i < values.length; i++) {
        values[i] = interpretName(names[i], values);
    }
    return (result < 0) ? null : values[result];
}

তবে কোডটি ডিবাগ করার জন্য পেয়ারা যতটা সোজা নয়, আসলে আমি n * 2রূপান্তরটি খুঁজে পাইনি ।

এই রূপান্তরটি দেখার কোনও উপায় বা এই কোডটি সহজেই ডিবাগ করার কোনও উপায় আছে?

সম্পাদনা: আমি বিভিন্ন মন্তব্য এবং পোস্ট উত্তর থেকে উত্তর যোগ করেছি

Holgerআমার প্রশ্নের উত্তরের মন্তব্যটির জন্য ধন্যবাদ , ল্যাম্বডা ব্লক থাকার পদ্ধতির ফলে আমাকে ল্যাম্বডা দেহের ভিতরে কী ঘটেছিল তা রূপান্তর প্রক্রিয়াটি দেখতে এবং ডিবাগ করার অনুমতি দেয়:

.map(
    n -> {
        Integer nr = n * 2;
        return nr;
    }
)

Stuart Marksপদ্ধতির উল্লেখ থাকার পদ্ধতির জন্য ধন্যবাদ আমাকে রূপান্তর প্রক্রিয়াটি ডিবাগ করার অনুমতিও দিয়েছে:

static int timesTwo(int n) {
    Integer result = n * 2;
    return result;
}
...
List<Integer> result2 = naturals.stream()
    .map(Java8Test::timesTwo)
    .collect(Collectors.toList());
...

Marlon Bernardesউত্তরের জন্য ধন্যবাদ আমি লক্ষ্য করেছি যে আমারগ্রহণটি কী হওয়া উচিত তা দেখায় না এবং উঁকি () ব্যবহারের ফলে ফলাফল প্রদর্শন করতে সহায়তা করেছে।


আপনাকে আপনার অস্থায়ী resultপরিবর্তনশীল হিসাবে ঘোষণা করার দরকার নেই Integer। একটি সরল intপাশাপাশি যদি তুমি কি করা উচিত mapপিং একটি intএকটি থেকে int...
হোলগার

এছাড়াও আমি যুক্ত করছি যে ইন্টেলিজ আইডিইএ 14-তে উন্নত ডিবাগার রয়েছে Now এখন আমরা লামডাস ডিবাগ করতে পারি।
মিখাইল

উত্তর:


86

Eclipse বা IntelliJ IDEA ব্যবহার করার সময় সাধারণত ল্যাম্বডা এক্সপ্রেশন ডিবাগ করতে আমার কোনও সমস্যা হয় না। কেবলমাত্র একটি ব্রেকপয়েন্ট নির্ধারণ করুন এবং পুরো ল্যাম্বডা এক্সপ্রেশনটি পরীক্ষা না করা নিশ্চিত করুন (কেবল ল্যাম্বডা দেহটি পরিদর্শন করুন)।

লম্বাডাস ডিবাগিং

peekস্ট্রিমের উপাদানগুলি পরীক্ষা করার জন্য আরেকটি পদ্ধতির ব্যবহার হ'ল :

List<Integer> naturals = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13);
naturals.stream()
    .map(n -> n * 2)
    .peek(System.out::println)
    .collect(Collectors.toList());

হালনাগাদ:

আমি মনে করি আপনি বিভ্রান্ত হয়ে যাচ্ছেন কারণ mapএটি intermediate operation- অন্য কথায়: এটি একটি অলস অপারেশন যা মৃত্যুদন্ড কার্যকর হওয়ার পরেই terminal operationকার্যকর করা হবে। সুতরাং আপনি যখন কল করবেন stream.map(n -> n * 2)তখন ল্যাম্বডা বডিটি এই মুহুর্তে কার্যকর করা হচ্ছে না। টার্মিনাল অপারেশন ডাকা হওয়ার পরে আপনাকে একটি ব্রেকপয়েন্ট স্থাপন করতে হবে এবং এটি পরীক্ষা করতে হবে ( collect, এই ক্ষেত্রে)।

আরও ব্যাখ্যার জন্য স্ট্রিম অপারেশনগুলি পরীক্ষা করুন ।

আপডেট 2:

হোলারের মন্তব্য উদ্ধৃত :

এটিকে এখানে কী জটিল করে তোলে তা হ'ল মানচিত্রের কল এবং ল্যাম্বডা এক্সপ্রেশনটি এক লাইনে রয়েছে সুতরাং একটি লাইন ব্রেকপয়েন্টটি দুটি সম্পূর্ণ সম্পর্কযুক্ত নয় actions

ঠিক পরে লাইন বিরতি োকানো map( আপনাকে কেবল ল্যাম্বডা এক্সপ্রেশনের জন্য ব্রেক পয়েন্ট নির্ধারণ করতে দেয়। এবং এটি অস্বাভাবিক নয় যে ডিবাগাররা একটি returnবিবৃতিটির মধ্যবর্তী মানগুলি দেখায় না । ল্যাম্বদা পরিবর্তন করা n -> { int result=n * 2; return result; } আপনাকে ফলাফল পরিদর্শন করার অনুমতি দেবে। আবার লাইনটি রেখার মাধ্যমে রেখার সময় যথাযথভাবে বিরতি প্রবেশ করান ...


মুদ্রণ পর্দার জন্য ধন্যবাদ। আপনার কাছে Eclipse এর কোন সংস্করণ আছে বা সেই সংলাপটি পেতে আপনি কী করেছিলেন? আমি ব্যবহার করার চেষ্টা inspectএবং display এবং পেতে n cannot be resolved to a variable। বিটিডব্লিউ, পিক খুব দরকারী তবে একবারে সমস্ত মান মুদ্রণ করে। রূপান্তরটি পরীক্ষা করতে আমি প্রতিটি পুনরুক্তি প্রক্রিয়া দেখতে চাই। এটা কি সুস্পষ্ট?
ফেডেরিকো পিয়াজা

আমি এক্লিপস কেপলার এসআর 2 ব্যবহার করছি (জাভা 8 সাপোর্টের সাথে এক্লিপের বাজার থেকে ইনস্টল করা)
মারলন বার্নার্ডস

আপনি কি Eclipse ব্যবহার করছেন? কেবল .mapলাইনে একটি ব্রেকপয়েন্ট নির্ধারণ করুন এবং একাধিকবার F8 চাপুন।
মারলন বার্নার্ডস

6
@ ফেড: যা এখানে এটি জটিল করে তোলে তা হ'ল কল mapএবং ল্যাম্বডা এক্সপ্রেশনটি এক লাইনে রয়েছে যাতে লাইন ব্রেকপয়েন্টটি দুটি সম্পূর্ণ সম্পর্কযুক্ত নয় on ঠিক পরে লাইন বিরতি োকানো map(আপনাকে কেবল ল্যাম্বডা এক্সপ্রেশনটির জন্য ব্রেক পয়েন্ট নির্ধারণ করতে দেয়। এবং এটি অস্বাভাবিক নয় যে ডিবাগাররা একটি returnবিবৃতিটির মধ্যবর্তী মানগুলি দেখায় না । ল্যাম্বডায় পরিবর্তন করা n -> { int result=n * 2; return result; }আপনাকে পরিদর্শন করার অনুমতি দেবে result। আবার লাইনটি রেখার মাধ্যমে লাইনটি যথাযথভাবে বিরতিতে প্রবেশ করান ...
হোলার

1
@ মারলন বার্নার্ডস: নিশ্চিত, আপনি এটির মন্তব্যের উদ্দেশ্য হিসাবে উত্তরের সাথে যুক্ত করতে পারেন: সামগ্রী উন্নত করতে সহায়তা করে। বিটিডব্লু।, আমি উদ্ধৃত পাঠ্য কোড বিন্যাস যুক্ত করে সম্পাদনা করেছি…
হোলার

33

ইন্টেলিজজে জাভা স্ট্রিম ডিবাগার প্লাগইন হিসাবে এই ক্ষেত্রে এর জন্য একটি দুর্দান্ত প্লাগইন রয়েছে। আপনার এটি পরীক্ষা করা উচিত: https://plugins.jetbrains.com/plugin/9696-java-stream-debugger?platform=hootsuite

এটি ট্রেস কারেন্ট স্ট্রিম চেইন বোতামটি যুক্ত করে আইডিইএ ডিবাগার সরঞ্জাম উইন্ডো প্রসারিত করে, যা স্রোত এপিআই কলগুলির একটি শৃঙ্খলের ভিতরে ডিবাগার থামলে সক্রিয় হয়।

এটির পৃথক স্ট্রিম ক্রিয়াকলাপগুলির সাথে কাজ করার জন্য দুর্দান্ত ইন্টারফেস রয়েছে এবং আপনাকে এমন কিছু মান অনুসরণ করার সুযোগ দেয় যা আপনার ডিবাগ করা উচিত।

জাভা স্ট্রিম ডিবাগার

আপনি এখানে ক্লিক করে ডিবাগ উইন্ডো থেকে ম্যানুয়ালি এটি চালু করতে পারেন:

এখানে চিত্র বর্ণনা লিখুন


23

নেটবিনগুলির সাথে ডিবাগিং ল্যাম্বডাসও ভাল কাজ করে। আমি নেটবিয়ানস 8 এবং জেডিকে 8u5 ব্যবহার করছি।

যদি আপনি কোনও ল্যাম্বডা আছে এমন কোনও লাইনে ব্রেকপয়েন্ট স্থাপন করেন তবে পাইপলাইনটি সেট আপ হওয়ার পরে আপনি একবারে আঘাত করতে পারবেন এবং তারপরে প্রতিটি স্ট্রিম উপাদানটির জন্য একবার। আপনার উদাহরণ ব্যবহার করে, ব্রেকআপপয়েন্টে আঘাত করার পরে আপনি প্রথমবারের মতো map()কলটি স্ট্রিম পাইপলাইন স্থাপন করবেন:

প্রথম ব্রেকপয়েন্ট

আপনি কল স্ট্যাক এবং স্থানীয় ভেরিয়েবল এবং প্যারামিটার মানগুলি mainযেমনটি আশা করেছিলেন তেমন দেখতে পাবেন। আপনি যদি এই পদক্ষেপ অবিরত রাখেন, "একই" ব্রেকপয়েন্টটি আবার আঘাত হানাবে, এই বারটি ল্যাম্বডায় কল করার পরে না:

এখানে চিত্র বর্ণনা লিখুন

মনে রাখবেন এই সময় কল স্ট্যাক গভীর স্ট্রিম যন্ত্রপাতি মধ্যে, এবং স্থানীয় ভেরিয়েবল ল্যামডা নিজেই না এনক্লোজিং এলাকাবাসী হয় mainপদ্ধতি। ( naturalsএটি পরিষ্কার করার জন্য আমি তালিকার মানগুলি পরিবর্তন করেছি ))

মারলন বার্নার্ডিস যেমন (+1) দেখিয়েছেন, peekপাইপলাইনে যেহেতু মানগুলি যায় সেভাবে আপনি তা পরীক্ষা করতে ব্যবহার করতে পারেন । আপনি যদি এটি একটি সমান্তরাল স্ট্রিম থেকে ব্যবহার করছেন তবে সতর্ক হন। মানগুলি বিভিন্ন থ্রেড জুড়ে একটি অনির্দেশ্য ক্রমে মুদ্রণ করা যেতে পারে। আপনি যদি কোনও ডিবাগিং ডেটা কাঠামোতে মানগুলি সঞ্চয় করে থাকেন তবে peekসেই ডেটা স্ট্রাকচার অবশ্যই থ্রেড-সেফ থাকতে হবে।

অবশেষে, আপনি যদি ল্যাম্বডাস (বিশেষত মাল্টি-লাইন স্টেটমেন্ট ল্যাম্বডাস) এর অনেকগুলি ডিবাগিং করছেন, তবে কোনও পদ্ধতিতে রেফারেন্স ব্যবহার করে ল্যাম্বডাকে উত্তোলন করা ভাল be উদাহরণ স্বরূপ,

static int timesTwo(int n) {
    return n * 2;
}

public static void main(String[] args) {
    List<Integer> naturals = Arrays.asList(3247,92837,123);
    List<Integer> result =
        naturals.stream()
            .map(DebugLambda::timesTwo)
            .collect(toList());
}

এটি আপনি ডিবাগ করার সময় কী চলছে তা দেখতে এটি আরও সহজ করে তুলতে পারে। তদ্ব্যতীত, পদ্ধতিগুলি এভাবে উত্তোলনের ফলে পরীক্ষার ইউনিট করা সহজ হয়। যদি আপনার ল্যাম্বডা এত জটিল হয় যে আপনাকে এটির মাধ্যমে একক পদক্ষেপ নেওয়া দরকার, আপনি সম্ভবত এটির জন্য একগুচ্ছ ইউনিট পরীক্ষা করতে চান।


আমার সমস্যাটি হ'ল আমি ল্যাম্বডা বডিটি ডিবাগ করতে পারি না তবে পদ্ধতির উল্লেখগুলি ব্যবহার করার ক্ষেত্রে আপনার দৃষ্টিভঙ্গি আমাকে যা চেয়েছিল তা দিয়ে আমাকে অনেক সহায়তা করেছিল। আপনি হোলার পদ্ধতির সাহায্যে আপনার উত্তরটি আপডেট করতে পারেন যা { int result=n * 2; return result; }বিভিন্ন লাইনে যুক্ত করেও পুরোপুরি কাজ করেছিল এবং উভয় উত্তর সহায়ক হওয়ায় আমি উত্তরটি গ্রহণ করতে পারি। অবশ্যই +1
ফেদেরিকো পিয়াজা

1
@ ফেড মনে হচ্ছে অন্যান্য উত্তর ইতিমধ্যে আপডেট হয়েছে, তাই আমার আপডেট করার দরকার নেই। আমি যাই হোক না কেন বহু-লাইন ল্যাম্বডাসকে ঘৃণা করি। :-)
স্টুয়ার্ট

1
@ স্টার্ট মার্কস: আমি একক লাইন ল্যাম্বডাসকেও পছন্দ করি। সুতরাং সাধারণত আমি ডিবাগিংয়ের পরে লাইন ব্রেকগুলি সরিয়ে ফেলি - যা অন্যান্য (সাধারণ) যৌগিক বিবৃতিতেও প্রযোজ্য⟩
হোলার

1
@ ফেড কোন উদ্বেগ নেই। আপনার পছন্দের যেকোন উত্তর গ্রহণ করা প্রশ্নকর্তা হিসাবে এটি আপনার পূর্বসূচী। +1 এর জন্য ধন্যবাদ।
স্টুয়ার্ট

1
আমি মনে করি যে পদ্ধতিগুলির রেফারেন্স তৈরি করা, ইউনিট পরীক্ষাগুলি সহজ করার পদ্ধতিগুলি আরও পাঠযোগ্য কোড তৈরি করে। দুর্দান্ত উত্তর! (+1)
মার্লন বার্নার্ডিস


6

কেবলমাত্র আরও আপডেট হওয়া বিশদ সরবরাহের জন্য (অক্টোবর 2019), ইন্টেলিজ এই ধরণের কোডটি ডিবাগ করতে একটি দুর্দান্ত সুন্দর ইন্টিগ্রেশন যুক্ত করেছে যা অত্যন্ত দরকারী।

যখন আমরা একটি ল্যাম্বডা যুক্ত একটি লাইনে থামি যখন আমরা টিপুন F7(পদক্ষেপে) তারপর ইন্টেলিজিজ হাইলাইট করবে ডিবাগ করার স্নিপেট কী হবে। ডিবাগ করার জন্য আমরা কী পরিবর্তন করতে পারি Tabএবং একবার এটি স্থির করার পরে আমরা F7আবার ক্লিক করি click

উদাহরণস্বরূপ এখানে কিছু স্ক্রিনশট রয়েছে:

1- টিপুন F7(পদক্ষেপে) কী, হাইলাইটগুলি প্রদর্শন করবে (বা নির্বাচন মোড) এখানে চিত্র বর্ণনা লিখুন

2- Tabডিবাগ করার জন্য স্নিপেট নির্বাচন করতে একাধিকবার ব্যবহার করুন এখানে চিত্র বর্ণনা লিখুন

3- F7প্রবেশ করতে কী টিপুন (পদক্ষেপে) এখানে চিত্র বর্ণনা লিখুন


1

আইডিই ব্যবহার করে ডিবাগিং সর্বদা সহায়ক, তবে জাভা স্টিমগুলি অলসভাবে মূল্যায়ন করার পরে টার্মিনাল পদ্ধতি অপারেশনের আগে একটি স্ট্রিমের প্রতিটি উপাদানগুলির মাধ্যমে ডিবাগিংয়ের আদর্শ উপায় হ'ল পিক () ব্যবহার করা, সুতরাং যদি কোনও টার্মিনাল পদ্ধতি চালু না করা হয় তবে সংশ্লিষ্ট স্ট্রিমটি মূল্যায়ন করা হবে না।

List<Integer> numFromZeroToTen = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

    numFromZeroToTen.stream()
        .map(n -> n * 2)
        .peek(n -> System.out.println(n))
        .collect(Collectors.toList());
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.