কাস্টম তুলনাকারীর সাথে ট্রিসেটে সংগ্রহ করতে স্ট্রিম ব্যবহার করা


92

জাভা 8 এ কাজ করা, আমি এর TreeSetমতো একটি সংজ্ঞায়িত করেছি :

private TreeSet<PositionReport> positionReports = 
        new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp));

PositionReport এটি বরং একটি সাধারণ শ্রেণি হিসাবে সংজ্ঞায়িত করা হয়:

public static final class PositionReport implements Cloneable {
    private final long timestamp;
    private final Position position;

    public static PositionReport create(long timestamp, Position position) {
        return new PositionReport(timestamp, position);
    }

    private PositionReport(long timestamp, Position position) {
        this.timestamp = timestamp;
        this.position = position;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public Position getPosition() {
        return position;
    }
}

এটি কাজ করে।

এখন আমি যে কোনও মান থেকে পুরানো TreeSet positionReportsসেখান থেকে এন্ট্রিগুলি সরাতে চাই timestamp। তবে আমি এটি প্রকাশের জন্য সঠিক জাভা 8 সিনট্যাক্সটি বের করতে পারি না।

এই প্রয়াসটি আসলে সংকলন করে, তবে আমাকে একটি TreeSetঅপরিজ্ঞাত তুলক সহ একটি নতুন দেয় :

positionReports = positionReports
        .stream()
        .filter(p -> p.timestamp >= oldestKept)
        .collect(Collectors.toCollection(TreeSet::new))

আমি কীভাবে প্রকাশ করব, যে আমি TreeSetএকটি তুলনাকারীর মতো একটিতে সংগ্রহ করতে চাই Comparator.comparingLong(PositionReport::getTimestamp)?

আমি এমন কিছু ভাবতাম

positionReports = positionReports
        .stream()
        .filter(p -> p.timestamp >= oldestKept)
        .collect(
            Collectors.toCollection(
                TreeSet::TreeSet(Comparator.comparingLong(PositionReport::getTimestamp))
            )
        );

তবে এটি পদ্ধতির উল্লেখগুলির জন্য বৈধ সিনট্যাক্স হিসাবে সংকলন / উপস্থিত হয় না।

উত্তর:


118

পদ্ধতির রেফারেন্সগুলি হ'ল যখন আপনার কাছে কোনও পদ্ধতি (বা নির্মাতা) রয়েছে যা ইতিমধ্যে আপনি যে লক্ষ্যটি পূরণ করার চেষ্টা করছেন তার আকৃতিটির সাথে ফিট করে। আপনি এক্ষেত্রে কোনও পদ্ধতি রেফারেন্স ব্যবহার করতে পারবেন না কারণ আপনি যে আকৃতিটিকে লক্ষ্য করছেন সেটি এমন একটি Supplierযা কোনও যুক্তি নেয় না এবং একটি সংগ্রহ প্রদান করে, তবে আপনার কাছে যা আছে তা একটি TreeSetযুক্তিযুক্ত গঠনকারী এবং আপনাকে সেই যুক্তিটি নির্দিষ্ট করতে হবে হয় সুতরাং আপনাকে কম সংক্ষিপ্ত পদ্ধতির গ্রহণ করতে হবে এবং ল্যাম্বডা এক্সপ্রেশনটি ব্যবহার করতে হবে:

TreeSet<Report> toTreeSet(Collection<Report> reports, long timestamp) {
    return reports.stream().filter(report -> report.timestamp() >= timestamp).collect(
        Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparingLong(Report::timestamp))
        )
    );
}

4
একটি বিষয় লক্ষণীয় হ'ল আপনার ট্রিসেটের ধরণ (এই ক্ষেত্রে পজিশন রিপোর্ট) তুলনীয় প্রয়োগ করে তবে আপনার তুলনা করার দরকার নেই।
xtrakBandit

35
@XtrakBandit- এ অনুসরণ করছেন - আবার আপনার যদি তুলনাকারী (প্রাকৃতিক বাছাই) নির্দিষ্ট করার প্রয়োজন না হয় - আপনি এটি খুব সংক্ষিপ্ত করে তুলতে পারেন:.collect(Collectors.toCollection(TreeSet::new));
জোশুয়া গোল্ডবার্গ

আমি এই ত্রুটি পেয়েছি:toCollection in class Collectors cannot be applied to given types
বাহাদির তাসদেমির

@ বাহাদিরটাসডেমির কোডটি কাজ করে। আপনি কেবল একটি যুক্তি দিয়ে যাচ্ছেন তা নিশ্চিত করুন Collectors::toCollection: একটি Supplierযা প্রত্যাবর্তন করে CollectionSupplierকেবল একটি একক বিমূর্ত পদ্ধতি সহ এটি একটি প্রকার, যার অর্থ এটি এই উত্তর হিসাবে ল্যাম্বডা অভিব্যক্তির লক্ষ্য হতে পারে। ল্যাম্বডা এক্সপ্রেশন অবশ্যই কোনও আর্গুমেন্ট নেবে না (তাই খালি যুক্তি তালিকা ()) এবং যে উপাদানটি আপনি সংগ্রহ করছেন সেই স্ট্রিমের উপাদানের প্রকারের সাথে মেলে এমন একটি উপাদান টাইপের সাথে একটি সংগ্রহ ফিরিয়ে দিন (এই ক্ষেত্রে ক TreeSet<PositionReport>)।
gdejohn

15

এটি কেবল পরবর্তী কোড ব্যবহার করা সহজ:

    positionReports = positionReports
        .stream()
        .filter(p -> p.timestamp >= oldestKept)
        .collect(
            Collectors.toCollection(()->new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp)
)));

9

আপনি কেবল শেষে একটি সোর্টসেটে রূপান্তর করতে পারেন (তবে শর্ত থাকে যে আপনি অতিরিক্ত অনুলিপিটি মনে করেন না)।

positionReports = positionReports
                .stream()
                .filter(p -> p.getTimeStamp() >= oldestKept)
                .collect(Collectors.toSet());

return new TreeSet(positionReports);

7
এটি করার সময় আপনার অবশ্যই যত্নবান হওয়া উচিত। এটি করার সময় আপনি উপাদানগুলি হারাতে পারেন। উপরে জিজ্ঞাসিত প্রশ্নের মতো, উপাদানগুলির প্রাকৃতিক তুলনামূলক কোনও ওপি ব্যবহার করতে চায় তার চেয়ে আলাদা। সুতরাং আপনি প্রাথমিক রূপান্তরটিতে, যেহেতু এটি একটি সেট, এটি কিছু উপাদানগুলি হারাতে পারে যা অন্য তুলনাকারী নাও থাকতে পারে (যেমন প্রথম তুলনাকারী compareTo() 0 হিসাবে ফিরে আসতে পারে অন্যটির সাথে কিছু তুলনা নাও থাকতে পারে All সমস্ত যেখানে compareTo()0 হয় এটি সেট হিসাবে হারিয়ে গেছে))
লুনিগড

6

সেখানে স্ট্রিম ব্যবহার ছাড়াই এই জন্য সংগ্রহ উপর একটি পদ্ধতি: default boolean removeIf(Predicate<? super E> filter)জাভাদোক দেখুন ।

সুতরাং আপনার কোডটি ঠিক এর মতো দেখতে পেল:

positionReports.removeIf(p -> p.timestamp < oldestKept);

1

ট্রিসেটের সমস্যাটি হ'ল আইটেমগুলি বাছাই করার জন্য আমরা যে তুলনা করতে চাই তা সেটগুলিতে আইটেমগুলি সন্নিবেশ করানোর সময় সদৃশ সনাক্তকরণের জন্যও ব্যবহৃত হয়। সুতরাং তুলনাকারী ফাংশনটি যদি দুটি আইটেমের জন্য 0 হয় তবে এটি একটিটিকে নকল হিসাবে বিবেচনা করে ভুলভাবে বাতিল করে দেয়।

সদৃশ সনাক্তকরণ আইটেমগুলির একটি পৃথক সঠিক হ্যাশকোড পদ্ধতি দ্বারা করা উচিত। আমি সমস্ত বৈশিষ্ট্য বিবেচনা করে হ্যাশকোডের সাথে সদৃশ প্রতিরোধ করতে একটি সাধারণ হ্যাশসেট ব্যবহার করতে পছন্দ করি (উদাহরণে আইডি এবং নাম) এবং আইটেমগুলি পাওয়ার পরে একটি সহজ সাজানো তালিকা ফিরে আসুন (উদাহরণে কেবল নাম অনুসারে বাছাই করা):

public class ProductAvailableFiltersDTO {

    private Set<FilterItem> category_ids = new HashSet<>();

    public List<FilterItem> getCategory_ids() {
        return category_ids.stream()
            .sorted(Comparator.comparing(FilterItem::getName))
            .collect(Collectors.toList());
    }

    public void setCategory_ids(List<FilterItem> category_ids) {
        this.category_ids.clear();
        if (CollectionUtils.isNotEmpty(category_ids)) {
            this.category_ids.addAll(category_ids);
        }
    }
}


public class FilterItem {
    private String id;
    private String name;

    public FilterItem(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof FilterItem)) return false;
        FilterItem that = (FilterItem) o;
        return Objects.equals(getId(), that.getId()) &&
                Objects.equals(getName(), that.getName());
    }

    @Override
    public int hashCode() {

        return Objects.hash(getId(), getName());
    }
}

1
positionReports = positionReports.stream()
                             .filter(p -> p.getTimeStamp() >= oldestKept)
                             .collect(Collectors.toCollection(() -> new 
TreeSet<PositionReport>(Comparator.comparingLong(PositionReport::getTimestamp))));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.