Java 8:基于可选条件进行流式处理和过滤

时间:2017-07-14 06:38:28

标签: java-8 java-stream optional

示例:过滤基于fromPrice和toPrice的价格的产品列表。它们既可以提供,也可以只提供一个。

  1. 查找价格大于fromPrice
  2. 的所有产品
  3. 查找价格低于“价格”的所有产品
  4. 查找价格介于价格和价格之间的所有产品
  5. 产品:

    namespace App.Adapters
    {
        class ExpandableListviewAdapter : BaseExpandableListAdapter
        {
            private Activity mContext;
            private List<ExpandableItem> mDataItems;
    
           public ExpandableListviewAdapter(Activity context, List<ExpandableItem> items)
                : base()
            {
                mContext = context;
                mDataItems = items;
    
                // Sort the groups and all of its child elements alphabetically.
                SortDataItems();
            }
    
            void SortDataItems()
            {
                // Sort each group alphabetically.
                mDataItems.Sort(delegate (ExpandableItem e1, ExpandableItem e2) 
                {
                    return e1.GroupTitle.CompareTo(e2.GroupTitle);
                });
    
                // Iterate over each group of items and sort the 
                // children alphabetically.
                foreach (var d in mDataItems)
                {
                    d.ChildItems.Sort(delegate (FMNavigationListItem i1, FMNavigationListItem i2)
                    {
                        return i1.DisplayAttributes[0].CompareTo(i2.DisplayAttributes[0]);
                    });
                }
            }
    
            public override View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                    convertView = mContext.LayoutInflater.Inflate(Resource.Layout.adapter_expandable_listview_listitem, null);
    
                FMNavigationListItem item = mDataItems[groupPosition].ChildItems[childPosition];
                convertView.FindViewById<TextView>(Resource.Id.adapter_expandable_listview_listitem_textview1).Text = item.DisplayAttributes[0];
                convertView.FindViewById<TextView>(Resource.Id.adapter_expandable_listview_listitem_textview2).Text = item.DisplayAttributes[1];
                convertView.FindViewById<TextView>(Resource.Id.adapter_expandable_listview_listitem_textview3).Text = item.DisplayAttributes[2];
    
                ImageButton i = convertView.FindViewById<ImageButton>(Resource.Id.adapter_expandable_listview_listitem_overflow_button);
                i.Click += OverflowButtonClicked;
                return convertView;
            }
    
            private void OverflowButtonClicked(object sender, EventArgs e)
            {
                Toast.MakeText(
                    mContext,
                    "Overflow button clicked!",
                    ToastLength.Short).Show();
            }
    
            public override View GetGroupView(int groupPosition, bool isExpanded, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                    convertView = mContext.LayoutInflater.Inflate(Resource.Layout.adapter_expandable_listview_header, null);
    
                // We expand all child objects from the group per default.
                // Normal default ist that all children are collapsed.
                ExpandableListView listView = (ExpandableListView)parent;
                listView.ExpandGroup(groupPosition);
    
                // Set the header title to be the group title.
                ExpandableItem item = mDataItems[groupPosition];
                convertView.FindViewById<TextView>(Resource.Id.adapter_expandable_listview_header_textview).Text = item.GroupTitle;
                return convertView;
            }
    
            public override int GroupCount
            {
                get
                {
                    return mDataItems.Count;
                }
            }
    
            public override bool HasStableIds
            {
                get
                {
                    return true;
                }
            }
    
            public override Java.Lang.Object GetChild(int groupPosition, int childPosition)
            {
                throw new NotImplementedException();
            }
    
            public override long GetChildId(int groupPosition, int childPosition)
            {
                return childPosition;
            }
    
            public override int GetChildrenCount(int groupPosition)
            {
                return mDataItems[groupPosition].ChildItems.Count;
            }
    
            public override bool IsChildSelectable(int groupPosition, int childPosition)
            {
                return true;
            }
    
            public override Java.Lang.Object GetGroup(int groupPosition)
            {
                throw new NotImplementedException();
            }
    
            public override long GetGroupId(int groupPosition)
            {
                return groupPosition;
            }
    
            public FMNavigationListItem ChildAt(int groupPosition, int childPosition)
            {
                return mDataItems[groupPosition].ChildItems[childPosition];
            }
        }
    
        /// <summary>
        /// 
        /// </summary>
        internal class ExpandableItem
        {
            public string GroupTitle;
            public List<FMNavigationListItem> ChildItems;
        }
    }
    

    PricePredicate:

    public class Product {
    
        private String id;
    
        private Optional<BigDecimal> price;
    
        public Product(String id, BigDecimal price) {
            this.id = id;
            this.price = Optional.ofNullable(price);
        }
    }
    

    过滤器:

    public class PricePredicate {
    
        public static Predicate<? super Product> isBetween(BigDecimal fromPrice, BigDecimal toPrice) {
            if (fromPrice != null && toPrice != null) {
                return product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(fromPrice) >= 0 &&
                        product.getPrice().get().compareTo(toPrice) <= 0;
            }
            if (fromPrice != null) {
                return product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(fromPrice) >= 0;
            }
            if (toPrice != null) {
                return product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(toPrice) <= 0;
            }
            return null;
        }
    }
    

    有没有办法改进我的谓词而不是if if null检查?可以用选项做什么?

2 个答案:

答案 0 :(得分:2)

不,可选不用于替换空检查。

但是如果两个参数都为null,那么可以通过避免重复来避免代码的改进,并避免返回null(这显然不是Predicate的有效值):

public static Predicate<Product> isBetween(BigDecimal fromPrice, BigDecimal toPrice) {
    Predicate<Product> result = product -> true;

    if (fromPrice != null) {
        result = result.and(product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(fromPrice) >= 0);
    }

    if (toPrice != null) {
        result = result.and(product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(toPrice) <= 0);
    }

    return result;
}

答案 1 :(得分:0)

您可以使用Apache Commons Lang,它提供null安全比较:

ObjectUtils.compare(from, to)

null is assumed to be less than a non-value