স্ট্রিমগুলির সাথে ব্যতিক্রমগুলি পরিচালনা করছে


10

আমার একটি রয়েছে Map<String,List<String>>এবং এটি রূপান্তরিত হওয়া চাই Map<String,List<Long>>কারণ Stringতালিকার প্রত্যেকটি একটি প্রতিনিধিত্ব করে Long:

Map<String,List<String>> input = ...;
Map<String,List<Long>> output= 
input.entrySet()
       .stream()
       .collect(toMap(Entry::getKey, e -> e.getValue().stream()
                                                      .map(Long::valueOf)
                                                      .collect(toList()))
               );

আমার মূল সমস্যাটি হ'ল প্রতিটিই Stringসঠিকভাবে উপস্থাপন করতে পারে না Long; কিছু সমস্যা হতে পারে। Long::valueOfব্যতিক্রম বাড়াতে পারে। যদি এটি হয় তবে আমি শূন্য বা খালি ফিরে যেতে চাইMap<String,List<Long>>

কারণ আমি এই outputমানচিত্রের পরে পুনরাবৃত্তি করতে চাই । তবে আমি কোনও ত্রুটি রূপান্তর গ্রহণ করতে পারি না; এমনকি একটিও না ভুল স্ট্রিং -> দীর্ঘ রূপান্তর ক্ষেত্রে আমি কীভাবে একটি খালি আউটপুট ফিরিয়ে আনতে পারি সে সম্পর্কে কোনও ধারণা?


আমি নামানের সমাধানের সাথে একমত আছি তবে দুর্ভাগ্যক্রমে ক্যাচ ব্লকে, আমি কী (এন্ট্রি :: getKey) পুনরুদ্ধার করতে ব্যর্থ হয়েছি যার জন্য স্ট্রিং -> দীর্ঘ রূপান্তরটি ভুল
অ্যান্টনবোয়ার্ফ

অনুরূপ আলোচনা এখানে: স্ট্রিং টু ইনট - সম্ভবত খারাপ ডেটা ব্যতিক্রমগুলি এড়াতে হবে যেখানে আমি অবশেষে রেইগেক্সের সাথে প্রাক-চেক করার সিদ্ধান্ত নিয়েছিলাম (পার্সলং দস্তাবেজগুলি একই পার্সিংয়ের নিয়ম ব্যবহার করে এবং আপনি LongStreamযদি emptyফলাফলগুলি সরিয়ে দেওয়ার পরিকল্পনা করেন তবে আপনি সম্ভবত একটি ফিরে আসতে চান )
এজাহারচর্লস

দুঃখিত আমি ভুল বুঝেছি. আমি ভেবেছিলাম আপনি একক এন্ট্রি খালি / নাল হিসাবে ফিরিয়ে দিতে চেয়েছিলেন; তবে এখন আমি মনে করি আপনি পুরো মানচিত্রটি বোঝাতে চাইছেন!
অজাহানচর্লস

1
মূল পয়েন্টটি কী তা সম্পূর্ণরূপে পরিষ্কার নয় - আপনি কোনও ত্রুটির ক্ষেত্রে খালি মানচিত্রটি ফিরিয়ে দিতে চান তবে এখনও "কী" মুদ্রণ করুন যেখানে ত্রুটি কনসোলে উপস্থিত হয়েছিল? আমি বলতে চাচ্ছি, প্রসঙ্গ যেখানে ব্যতিক্রম হাজির সাধারণত কল স্ট্যাক আপ পরিবাহিত হয় সম্পর্কে তথ্য মধ্যে ব্যতিক্রম। তা নির্বিশেষে: আপনি স্ট্রিম সম্পর্কে বিশেষভাবে জিজ্ঞাসা করেছিলেন, তবে আমি নেস্টেড "সংগ্রহ" কলগুলি এড়াতে দৃ strongly়ভাবে পরামর্শ দেব । যে লোকেরা এটি পরবর্তী সময়ে বজায় রাখতে হবে (এবং এটি ভবিষ্যতে আপনার ভবিষ্যত হতে পারে !) অবাক করে বলবে যে এইচ ... আপনি সেখানে কী করেছিলেন? কমপক্ষে কিছু সঠিকভাবে নামকরণকারী সহায়ক পদ্ধতি প্রবর্তন করুন।
মার্কো 13

উত্তর:


4

catchব্যতিক্রম সম্পর্কে কীভাবে স্পষ্ট :

private Map<String, List<Long>> transformInput(Map<String, List<String>> input) {
    try {
        return input.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream()
                        .map(Long::valueOf)
                        .collect(Collectors.toList())));
    } catch (NumberFormatException nfe) {
        // log the cause
        return Collections.emptyMap();
    }
}

ঠিক আছে ভাল লাগছে ... তবে ক্যাচে (এনএফই) আমি কী (এন্ট্রি :: getKey) এর নির্দিষ্ট মান এবং ভুল স্ট্রিংয়ের জন্য এটির ব্যর্থতা পুনরুদ্ধার করতে চাই যাতে এটি যেখানে ভুল হয় ঠিক সেখানে লগইন করতে পারি। এটা কি সম্ভব ?
আন্তনবোরফ

@ অ্যান্টনবোআরফ আপনি যদি কেবল কীটিটি লগ করতে চান, যার জন্য এটি স্ট্রিংকে বিশ্লেষণ করতে ব্যর্থ হয়েছে, ব্যবহার করুনnfe.getMessage()
নমন

1
@ অ্যান্টনবোআরফ ব্যতিক্রমের বার্তায় ত্রুটিযুক্ত ইনপুট স্ট্রিং থাকবে। দায়িত্বশীল কীটি পেতে, আমি একটি স্পষ্ট অনুসন্ধান করব, কেবল তখনই ব্যতিক্রম ঘটেছিল, যেমনinput.entrySet().stream() .filter(e -> e.getValue().stream().anyMatch(s -> !new Scanner(s).hasNextLong())) .map(Map.Entry::getKey) .findAny()
হলগার

@ধারক. ধন্যবাদ ... এটি জটিল বলে মনে হচ্ছে ... আমি ভাবছি যদি লুপ জাভা 5 এর জন্য স্ট্যান্ডার্ড ব্যবহার করা আমার ক্ষেত্রে ভাল না
আন্তনবোর্ফ

@ অ্যান্টনবোআরফ কেবল উভয়ই বাস্তবায়ন করুন এবং তুলনা করুন…
হলগার

3

আমি ব্যক্তিগতভাবে Optionalসংখ্যা পার্সিংয়ের চারপাশে একটি ইনপুট সরবরাহ করতে চাই :

public static Optional<Long> parseLong(String input) {
    try {
        return Optional.of(Long.parseLong(input));
    } catch (NumberFormatException ex) {
        return Optional.empty();
    }
}

তারপরে, আপনার নিজের কোড ব্যবহার করুন (এবং খারাপ ইনপুট উপেক্ষা করে ):

Map<String,List<String>> input = ...;
Map<String,List<Long>> output= 
input.entrySet()
       .stream()
       .collect(toMap(Entry::getKey, e -> e.getValue().stream()
                                                      .map(MyClass::parseLong)
                                                      .filter(Optional::isPresent)
                                                      .map(Optional::get)
                                                      .collect(toList()))
               );

অতিরিক্তভাবে, এটি আরও সংহত করতে একটি সহায়ক পদ্ধতি বিবেচনা করুন:

public static List<Long> convertList(List<String> input) {
    return input.stream()
        .map(MyClass::parseLong).filter(Optional::isPresent).map(Optional::get)
        .collect(Collectors.toList());
}

public static List<Long> convertEntry(Map.Entry<String, List<String>> entry) {
    return MyClass.convertList(entry.getValue());
}

তারপরে আপনি নিজের স্ট্রিমের সংগ্রহে ফলাফলগুলি ফিল্টার করতে পারবেন:

Map<String, List<Long>> converted = input.entrySet().stream()
    .collect(Collectors.toMap(Entry::getKey, MyClass::convertEntry));

আপনি খালি Optionalজিনিসগুলি আপনার তালিকাগুলিতেও রাখতে পারেন এবং তারপরে তাদের মূল সূচকে নতুন List<Optional<Long>>(পরিবর্তে List<Long>) এর সাথে মূলের সাথে তুলনা করে List<String>আপনি স্ট্রিংটি খুঁজে পেতে পারেন যা কোনও ভ্রান্ত ইনপুটগুলির কারণ হয়েছিল। আপনি এই ব্যর্থতাগুলিকে কেবল লগ ইন করতে পারেনMyClass#parseLong

তবে, যদি আপনার ইচ্ছাটি কোনও খারাপ ইনপুটটি মোটেও পরিচালনা না করে , তবে আপনি যা ধরার চেষ্টা করছেন তা পুরো প্রবাহকে ঘিরে (নমনের উত্তর অনুসারে) আমি যে পথটি নেব তা হ'ল।


2

আপনি StringBuilderব্যতিক্রম সহ একটি কী তৈরি করতে পারেন এবং eleনীচের মতো সংখ্যাযুক্ত কিনা তা পরীক্ষা করতে পারেন ,

 public static Map<String, List<Long>> transformInput(Map<String, List<String>> input) {
    StringBuilder sb = new StringBuilder();
    try {
    return input.entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream()
                    .map(ele->{
                        if (!StringUtils.isNumeric(ele)) {
                            sb.append(e.getKey()); //add exception key
                            throw new NumberFormatException();
                        }
                        return Long.valueOf(ele);
                    })
                    .collect(Collectors.toList())));
} catch (NumberFormatException nfe) {
    System.out.println("Exception key "+sb);
    return Collections.emptyMap();
}
}

আশা করি এটা সাহায্য করবে.


0

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

// StringUtils.java
public static boolean isNumeric(String string) {
    try {
        Long.parseLong(string);
        return true;
    } catch(NumberFormatException e) {
        return false;
    }
}

এটি সবকিছু যত্ন নেবে।

এবং এটি আপনার প্রবাহে ব্যবহার করুন।

Map<String, List<Long>> newMap = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> mapToLongValues(entry.getValue())));

public List<Long> mapToLongValues(List<String> strs) {
    return strs.stream()
        .filter(Objects::nonNull)
        .filter(StringUtils::isNumeric)
        .map(Long::valueOf)
        .collect(Collectors.toList());
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.