শর্তাধীন স্ট্রিম থেকে প্রথমে (শূন্য সূচক সহ) উপাদানটি সরান


10

আমার নিম্নলিখিত কোড রয়েছে:

Stream<String> lines = reader.lines();

যদি মুষ্টির স্ট্রিং সমান হয় তবে "email"আমি প্রথম স্ট্রিমটি স্ট্রিম থেকে সরাতে চাই। স্ট্রিমের অন্যান্য স্ট্রিংয়ের জন্য আমার এই চেকটির দরকার নেই।

আমি কীভাবে এটি পেতে পারি?

পুনশ্চ

অবশ্যই আমি এটিকে তালিকায় রূপান্তর করতে পারি, তারপরে লুপের জন্য পুরানো স্কুলটি ব্যবহার করুন তবে আরও আমার আবার প্রবাহের প্রয়োজন।


3
এবং যদি দ্বিতীয় উপাদানটি "ইমেল" হয় তবে আপনি কি এটি ফেলে দিতে চান না?
মাইকাল্ক

@ মিমিকল আপনি সঠিক
gstackoverflow

হুম ... সেখানে skip(long n)প্রথম nউপাদানগুলি এড়িয়ে গেছে , তবে আপনি জানেন না আপনি এটি কোনওভাবে কন্ডিশন করতে পারেন কিনা ...
deHaar

4
আপনি যদি সিএসভি ফাইলের শিরোনামের বিষয়ে কথা বলছেন তবে স্ট্রিমের প্রথম দুটি স্ট্রিং সমান "ইমেল" এর সমান হওয়ার সম্ভাবনা থাকলে @ জিস্ট্যাকওভারফ্লো যদি আপনি ব্যবহার করতে পারেনstream.dropWhile(s -> s.equals("email"));
ইরিত্রিয়ান

1
@ ইরিত্রিয়ান এটি কেবল এটি পোস্ট করবে;)
YCF_L

উত্তর:


6

আপনি যখন এটির লাইন স্রোত তৈরির পরে পাঠক একটি অনির্ধারিত অবস্থায় থাকবেন তখন এটি করার আগে এটি একটি সুসংজ্ঞায়িত অবস্থায় রয়েছে is

সুতরাং আপনি করতে পারেন

String firstLine = reader.readLine();
Stream<String> lines = reader.lines();
if(firstLine != null && !"email".equals(firstLine))
    lines = Stream.concat(Stream.of(firstLine), lines);

যা আমার মতে সবচেয়ে পরিষ্কার সমাধান। মনে রাখবেন যে এটি জাভা 9 এর মতো নয়, এটি dropWhileমিললে একাধিক লাইন ফেলে দেবে।


সম্মত হন - এই সমাধানটি আরও ভাল তবে ড্রপওয়াইল - দ্বিতীয় স্থান। দুর্ভাগ্যক্রমে লেখক পৃথক উত্তর হিসাবে এই ধারণা পোস্ট না করার সিদ্ধান্ত নিয়েছে
gstackoverflow

3

যদি আপনার তালিকাগুলি না থাকে এবং এটি অবশ্যই Streamএকটি দিয়েই করতে পারেন তবে আপনি এটি পরিবর্তনশীল দিয়ে করতে পারেন।

জিনিসটি হ'ল আপনি কেবলমাত্র একটি ভেরিয়েবল ব্যবহার করতে পারেন যদি এটি "চূড়ান্ত" বা "কার্যকরভাবে চূড়ান্ত" হয় তবে আপনি আক্ষরিক বুলিয়ান ব্যবহার করতে পারবেন না। আপনি এখনও এটি দিয়ে করতে পারেন AtomicBoolean:

Stream<String> stream  = Arrays.asList("test", "email", "foo").stream();

AtomicBoolean first = new AtomicBoolean(true);
stream.filter(s -> {
    if (first.compareAndSet(true, false)) {
        return !s.equals("email");
    }
    return true;
})
// Then here, do whatever you need
.forEach(System.out::println);

দ্রষ্টব্য: আমি "বাহ্যিক ভেরিয়েবল" ব্যবহার করা পছন্দ করি না Streamকারণ পার্শ্ব প্রতিক্রিয়াগুলি কার্যকরী প্রোগ্রামিং দৃষ্টান্তের একটি খারাপ অভ্যাস। আরও ভাল বিকল্প স্বাগত জানাই।


এটি ব্যবহার করে compareAndSetপতাকাটি একই সাথে সেট করা এবং পাওয়ার এক দুর্দান্ত উপায় nice
f1sh

stream.filter(!first.compareAndSet(true, false) || !s.equals("email"))বিতর্কযোগ্য যদিও করতে পারে ।
জোপ এগজেন

1
predicateঅবশ্যই রাষ্ট্রহীন হতে হবে
ZhekaKozlov

3
যদি এখানে ব্যবহার করে AtomicBooleanসমান্তরাল স্ট্রিমগুলি পূরণ করা হয় ( compareAndSetপ্রস্তাবিত ব্যবহার হিসাবে ) তবে এটি সম্পূর্ণরূপে ভুল কারণ এটি কেবলমাত্র স্ট্রিমটি ক্রমযুক্ত হলে কাজ করবে। তবে আপনি যদি এই কৌশলটি ব্যবহার করেন stream.sequential().filter(...)তবে আমি সম্মতি জানাই এটি কার্যকর হবে।
ড্যানিয়েল

3
ডানিয়েল আপনি ঠিক বলেছেন, সমান্তরাল প্রক্রিয়াকরণকে সমর্থন না করার সময় এই পদ্ধতিটি থ্রেড সেফ কনস্ট্রাক্টের (প্রতিটি উপাদানগুলির জন্য) ব্যয় করছে। রাষ্ট্রীয় ফিল্টারগুলির সাথে এতগুলি উদাহরণ এই ক্লাসগুলির ব্যবহারের কারণ হ'ল থ্রেড সুরক্ষা ব্যতীত কোনও সমতুল্য নেই এবং লোকেরা তাদের
হোলার

1

ফাইলটির প্রতিটি লাইনের শর্তটি পরীক্ষা করা এড়াতে, আমি কেবল প্রথম লাইনটি পৃথকভাবে পড়তে এবং পরীক্ষা করতে পারি, তারপরে শর্তটি পরীক্ষা না করেই বাকি লাইনে পাইপলাইনটি চালনা করতাম:

String first = reader.readLine();
Stream<String> firstLines = Optional.of(first)
        .filter(s -> !"email".equals(s))
        .map(s -> Stream.of(s))
        .orElseGet(() -> Stream.empty());

Stream<String> lines = Stream.concat(firstLines, reader.lines());

জাভা 9+ তে সহজ:

Stream<String> firstLines = Optional.of(first)
        .filter(s -> !"email".equals(s))
        .stream();

Stream<String> lines = Stream.concat(firstLines, reader.lines());

4
জাভা 9 আরও সহজ:Stream.ofNullable(first).filter(not("email"::equals))
হোলার

1

@ আর্নউডস উত্তর সঠিক। আপনি প্রথম লাইনের জন্য একটি স্ট্রিম তৈরি করতে পারেন এবং তারপরে নীচের মতো তুলনা করতে পারেন,

Stream<String> firstLineStream = reader.lines().limit(1).filter(line -> !line.startsWith("email"));;
Stream<String> remainingLinesStream = reader.lines().skip(1);
Stream.concat(firstLineStream, remainingLinesStream);

এমনকি আপনি যদি একটি ফিল্টার ব্যবহার করেন তবে এটি প্রতিটি লাইনের জন্য গণনা করা হবে। বিশাল ফাইলের ক্ষেত্রে এটি পারফরম্যান্সের কারণ হতে পারে। সীমা ক্ষেত্রে, এটি একবার মাত্র তুলনা করা হবে।
কোড_মড

পাঠকের পক্ষে কাজ না করা ছাড়াও limit(0)অবশ্যই হওয়া উচিত limit(1)...
হোলার

আমি টেস্টিমগের পরে 0 সীমাতে উত্তর সম্পাদনা করেছি।
কোড_মড

1
আমি দেখতে পাচ্ছি যে আপনি এটি পরিবর্তন করেছেন, কিন্তু .limit(0).filter(line -> !line.startsWith("email"))কোনও লাভ নেই। শিকারী কখনই মূল্যায়ন করবে না। স্ট্রিমগুলি পুনরুত্পাদন করতে সক্ষম স্ট্রিম উত্সের জন্য, limit(1)প্রথমটিতে এবং skip(1)দ্বিতীয়টিতে সংমিশ্রণটি সঠিক হবে। পাঠকের মতো একটি স্ট্রিম উত্সের জন্য, না কাজ করবে limit(1)না limit(0)। আপনি সবেমাত্র পরিবর্তন করেছেন যে কোন রেখাটি নিঃশর্ত গিলে যায়। এমনকি যদি আপনি এমন কোনও সংমিশ্রণ খুঁজে পান যা পছন্দসই কাজটি করতে ঘটে তবে তা অনির্দিষ্ট, বাস্তবায়ন নির্ভর আচরণের ভিত্তিতে হবে।
হোলার

0

তাদের সূচকের উপর ভিত্তি করে উপাদানগুলিকে ফিল্টার করতে, আপনি AtomicIntegerকোনও প্রক্রিয়া করার সময় সঞ্চয় এবং বর্ধিত সূচক ব্যবহার করতে পারেন Stream:

private static void filter(Stream<String> stream) {
  AtomicInteger index = new AtomicInteger();
  List<String> result = stream
      .filter(el -> {
        int i = index.getAndIncrement();
        return i > 0 || (i == 0 && !"email".equals(el));
      })
      .collect(toList());
  System.out.println(result);
}

public static void main(String[] args) {
  filter(Stream.of("email", "test1", "test2", "test3")); 
  //[test1, test2, test3]

  filter(Stream.of("test1", "email", "test2", "test3")); 
  //[test1, email, test2, test3]

  filter(Stream.of("test1", "test2", "test3")); 
  //[test1, test2, test3]
}

এই পদ্ধতির সাহায্যে প্রথমটি নয়, কোনও সূচকে উপাদানগুলি ফিল্টার করতে দেয়।


0

এই স্নিপেট থেকে কিছুটা অনুপ্রেরণা পেয়ে আরও কিছুটা বিশৃঙ্খলা

আপনি এমন একটি তৈরি করতে পারেন Stream<Integer>যা সূচকে উপস্থাপন করবে এবং Stream<String>একটি তৈরি করতে আপনার সাথে এটি "জিপ" করুনStream<Pair<String, Integer>>

তারপরে সূচকটি ব্যবহার করে ফিল্টার করুন এবং এটিকে আবার মানচিত্র করুন Stream<String>

public static void main(String[] args) {
    Stream<String> s = reader.lines();
    Stream<Integer> indexes = Stream.iterate(0, i -> i + 1);

    zip(s, indexes)
        .filter(pair -> !(pair.getKey().equals("email") && pair.getValue() == 0))
        .map(Pair::getKey)
        .forEach(System.out::println);
}

private static Stream<Pair<String,Integer>> zip(Stream<String> stringStream, Stream<Integer> indexesStream){
    Iterable<Pair<String,Integer>> iterable = () -> new ZippedWithIndexIterator(stringStream.iterator(), indexesStream.iterator());
    return StreamSupport.stream(iterable.spliterator(), false);
}

static class ZippedWithIndexIterator implements Iterator<Pair<String, Integer>> {
    private final Iterator<String> stringIterator;
    private final Iterator<Integer> integerIterator;

    ZippedWithIndexIterator(Iterator<String> stringIterator, Iterator<Integer> integerIterator) {
        this.stringIterator = stringIterator;
        this.integerIterator = integerIterator;
    }
    @Override
    public Pair<String, Integer> next() {
        return new Pair<>(stringIterator.next(), integerIterator.next());
    }
    @Override
    public boolean hasNext() {
        return stringIterator.hasNext() && integerIterator.hasNext();
    }
}

0

এখানে সঙ্গে উদাহরণ Collectors.reducing। কিন্তু শেষ পর্যন্ত যাইহোক একটি তালিকা তৈরি করে।

Stream<String> lines = Arrays.asList("email", "aaa", "bbb", "ccc")
        .stream();

List reduceList = (List) lines
        .collect(Collectors.reducing( new ArrayList<String>(), (a, v) -> {
                    List list = (List) a;
                    if (!(list.isEmpty() && v.equals("email"))) {
                        list.add(v);
                    }
                    return a;
                }));

reduceList.forEach(System.out::println);

0

এটা চেষ্টা কর:

MutableBoolean isFirst = MutableBoolean.of(true);
lines..dropWhile(e -> isFirst.getAndSet(false) && "email".equals(e))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.