هل هناك وسيلة أنيقة لإزالة القيم الخالية في حين بتحويل مجموعة باستخدام الجوافة؟

StackOverflow https://stackoverflow.com/questions/1802629

سؤال

ولدي سؤال حول تبسيط بعض مجموعة معالجة التعليمات البرمجية، عند استخدام مجموعات جوجل (<م> تحديث : <وأ href = "https://code.google.com/p/guava-libraries/" يختلط = "noreferrer"> الجوافة ).

ولقد حصلت على مجموعة من الأشياء "الكمبيوتر"، وأريد أن ينتهي مع مجموعة من من ليالي "معرف المورد". ويتم ذلك كما يلي:

Collection<Computer> matchingComputers = findComputers();
Collection<String> resourceIds = 
    Lists.newArrayList(Iterables.transform(matchingComputers, new Function<Computer, String>() {
    public String apply(Computer from) {
        return from.getResourceId();
    }
}));

والآن، getResourceId() قد ترجع فارغة (والمتغيرة التي ليس خيارا الآن)، ولكن في هذه الحالة أود أن حذف الأصفار من مجموعة سلسلة الناتجة عن ذلك.

وهنا طريقة واحدة لتصفية القيم الخالية من:

Collections2.filter(resourceIds, new Predicate<String>() {
    @Override
    public boolean apply(String input) {
        return input != null;
    }
});

هل يمكن وضع كل ذلك معا مثل هذا:

Collection<String> resourceIds = Collections2.filter(
Lists.newArrayList(Iterables.transform(matchingComputers, new Function<Computer, String>() {
    public String apply(Computer from) {
        return from.getResourceId();
    }
})), new Predicate<String>() {
    @Override
    public boolean apply(String input) {
        return input != null;
    }
});

ولكن هذا لا يكاد أنيقة، ناهيك عن قراءة، لهذه المهمة بسيطة! في الواقع، فإن عادي كود جافا القديم (مع عدم وجود المسند نزوة أو وظيفة الأشياء على الإطلاق) أن يكون القول أنظف بكثير:

Collection<String> resourceIds = Lists.newArrayList();
for (Computer computer : matchingComputers) {
    String resourceId = computer.getResourceId();
    if (resourceId != null) {
        resourceIds.add(resourceId);
    }
}

وعن طريق ما سبق هو بالتأكيد أيضا خيار، ولكن من باب الفضول (والرغبة في معرفة المزيد من مجموعات جوجل) و يمكنك أن تفعل نفس الشيء في بعض الطريق أقصر أو أكثر أناقة باستخدام مجموعات جوجل

هل كانت مفيدة؟

المحلول

وهناك بالفعل المسند في <لأ href = "https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/base/Predicates.html" يختلط = "noreferrer" > Predicates التي ستساعدك هنا - Predicates.notNull() - ويمكنك استخدام Iterables.filter() وحقيقة أن Lists.newArrayList() يمكن أن يستغرق Iterable لتنظيف هذا أكثر قليلا

Collection<String> resourceIds = Lists.newArrayList(
  Iterables.filter(
     Iterables.transform(matchingComputers, yourFunction),
     Predicates.notNull()
  )
);

إذا كنت لا تحتاج في الواقع Collection، مجرد Iterable، ثم الدعوة Lists.newArrayList() يمكن أن يذهب بعيدا جدا، وكنت خطوة واحدة نظافة مرة أخرى!

وأظن أنك قد وجدت أن Function سوف تأتي في متناول اليدين مرة أخرى، وسوف يكون مفيدا للغاية كما أعلن

public class Computer {
    // ...
    public static Function<Computer, String> TO_ID = ...;
}

والذي ينظف هذا الأمر أكثر من ذلك (وسوف تعزز إعادة الاستخدام).

نصائح أخرى

وهناك بعض الشيء "أجمل" جملة مع <لأ href = "https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/FluentIterable.html" يختلط = " noreferrer "> FluentIterable (ومنذ الجوافة 12):

ImmutableList<String> resourceIds = FluentIterable.from(matchingComputers)
    .transform(getResourceId)
    .filter(Predicates.notNull())
    .toList();

static final Function<Computer, String> getResourceId =
    new Function<Computer, String>() {
        @Override
        public String apply(Computer computer) {
            return computer.getResourceId();
        }
    };

لاحظ أن قائمة عاد هو ImmutableList. ومع ذلك، يمكنك استخدام أسلوب copyInto() إلى صب العناصر في مجموعة التعسفي.

أولا، فما استقاموا لكم فاستقيموا إنشاء عامل تصفية ثابت في مكان ما:

public static final Predicate<Object> NULL_FILTER =  new Predicate<Object>() {
    @Override
    public boolean apply(Object input) {
            return input != null;
    }
}

وبعد ذلك يمكنك استخدام:

Iterable<String> ids = Iterables.transform(matchingComputers,
    new Function<Computer, String>() {
        public String apply(Computer from) {
             return from.getResourceId();
        }
    }));
Collection<String> resourceIds = Lists.newArrayList(
    Iterables.filter(ids, NULL_FILTER));

ويمكنك استخدام نفس المرشح لاغية في كل مكان في التعليمات البرمجية.

إذا كنت تستخدم نفس الوظيفة الحوسبة في أماكن أخرى، يمكنك جعل ذلك ثابت جدا، وترك فقط:

Collection<String> resourceIds = Lists.newArrayList(
    Iterables.filter(
        Iterables.transform(matchingComputers, RESOURCE_ID_PROJECTION),
        NULL_FILTER));

وانها بالتأكيد ليست لطيفة مثل C # يعادل سيكون، ولكن هذا هو كل شيء ذاهب للحصول على الكثير أجمل في جافا 7 مع الإغلاق وطرق الإرشاد:)

هل يمكن كتابة الأسلوب الخاص بك مثل ذلك. هذا سيقوم بتصفية بلا قيم لأي وظيفة أن يعود لاغية من أسلوب تطبيق.

   public static <F, T> Collection<T> transformAndFilterNulls(List<F> fromList, Function<? super F, ? extends T> function) {
        return Collections2.filter(Lists.transform(fromList, function), Predicates.<T>notNull());
    }

ويمكن بعد ذلك استدعاء الأسلوب مع التعليمات البرمجية التالية.

Collection c = transformAndFilterNulls(Lists.newArrayList("", "SD", "DDF"), new Function<String, Long>() {

    @Override
    public Long apply(String s) {
        return s.isEmpty() ? 20L : null;
    }
});
System.err.println(c);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top