栈+哈希表(或者稀疏数组)解决安卓购物车新添加货物置顶的问题

来源:互联网 发布:妖气漫画网软件 编辑:程序博客网 时间:2024/05/20 05:11

最近在做仿淘宝购物的APP(目前已经完成,有时间就把这个项目写出来),在做购物车这一块的时候,我是把数据先转化为json数据,然后通过sharedpreferences来把数据保存到本地内存中(至少用户没有登录的情况下可以这么做),我们知道sharedpreferences是通过键值对来存储数据的(不清楚的同学请移步Android源代码分析之sharedpreferences),key值可以随便给定一个常量,取的时候也是需要通过这个key来取的,以下即是存储的代码:

public void commit(){    List<ShoppingCart> carts = sparseToList();//ShoppingCart是对商品属性的一个封装类,sparseToList()下面会给出解释    PreferencesUtils.putString(mContext,CART_JSON,JSONUtil.toJSON(carts));//JSONUtil是对json数据转换功能进行封装的一个类}

在PreferencesUtils类里面封装了对sharedpreferences的调用:

public static boolean putString(Context context, String key, String value) {        SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);        SharedPreferences.Editor editor = settings.edit();        editor.putString(key, value);        return editor.commit();    }

在最开始做的时候对于carts中商品的排序是根据商品的id来的,以下是spareseToList函数的代码:

private List<ShoppingCart> sparseToList(){        int size = datas.size();//datas是存储商品的稀疏数组        List<ShoppingCart> list = new ArrayList<>(size);        for (int i=0;i<size;i++){            list.add(datas.valueAt(i));        }        return list;    }
上面这个函数的作用是把稀疏数组里面的元素添加到新建的List中,稀疏数组插入元素的时候是通过二分法来判断数组里面是否已经包含了这个key值,如果包含了,那么只需要修改这个key对应的value值即可,如果没有包含,那么需要将key和value添加到稀疏数组当中,源代码如下:
 public void put(int key, E value) {        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);        if (i >= 0) {            mValues[i] = value;        } else {            i = ~i;            if (i < mSize && mValues[i] == DELETED) {                mKeys[i] = key;                mValues[i] = value;                return;            }            if (mGarbage && mSize >= mKeys.length) {                gc();                // Search again because indices may have changed.                i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);            }            mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);            mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);            mSize++;        }    }
其中二分查找的源代码如下:
static int binarySearch(int[] array, int size, int value) {        int lo = 0;        int hi = size - 1;        while (lo <= hi) {            final int mid = (lo + hi) >>> 1;            final int midVal = array[mid];            if (midVal < value) {                lo = mid + 1;            } else if (midVal > value) {                hi = mid - 1;            } else {                return mid;  // value found            }        }        return ~lo;  // value not present    }
如果源代码有些地方看不懂,可以自己去搜一下稀疏数组。既然用到了二分法,那么稀疏数组里面的key值是从小到大有序排列的,所以回到前面所说的商品是以商品id为key值,商品cart为value,添加商品到购物车的代码如下:
public void put(ShoppingCart cart){       ShoppingCart temp =  datas.get(cart.getId().intValue());//查询购物车里面是否已经有这一件商品了        if(temp !=null){                                       //如果有的话那么只需要将数量+1            temp.setCount(temp.getCount()+1);        }        else{                                                  //如果没有就添加到购物车            temp = cart;            temp.setCount(1);        }        datas.put(cart.getId().intValue(),temp);        commit();//即上面第一段的commit代码    }

这里以商品id来排序会造成一个比较糟糕的用户体验,即用户添加一件商品到购物车,然而购物车的第一件商品并不一定是刚刚用户添加的那件货物,当用户添加了很多件商品之后再添加其他的一件商品,可能这件商品会在用户的购物屏幕上“消失”,用户还得翻滚屏幕来寻找刚刚添加的那件商品。所以我们不能使用商品id来作为稀疏数组的key值,那该用商品的什么属性来作为key呢?用时间吗?听起来不错,不过这并不是商品的属性,那有没有更好的办法来使得先进来的商品最后才显示出来呢?对了,使用栈,可是使用java本身所具有的那个stack栈的话,如果要随机访问datas.get(cart.getId().intValue());里面的元素,那么对于栈来说效率太差了,那么我们可不可以存储和读取数据的时候使用栈,而随机访问当中的元素的时候就使用哈希表或者稀疏数组,我这里是使用了稀疏数组,至于为什么不用哈希表,大家可以参看稀疏数组相比于哈希表(HashMap/HashTable)的优点。所以添加商品到购物车的代码如下:

datas = new SparseArray<>(10);shoppingDatas = new LinkedList<>();//这里使用LinkedList来取代stack使用,相比于stack来说前者效率更好
public void put(ShoppingCart cart){          ShoppingCart temp =  datas.get(cart.getId().intValue());//查询购物车里面是否已经有这一件商品了        if(temp !=null){            temp.setCount(temp.getCount() + 1);                 //因为商品个数是商品的属性,所以无论是栈还是数组里面的数据都会发生改变        }        else{            temp = cart;            temp.setCount(1);            shoppingDatas.push(cart);                         //数据同时添加到栈里面和稀疏数组里面        }        datas.put(cart.getId().intValue(), temp);        commit();    }
数据存储到内存中的代码如下:
public void commit(){        List<ShoppingCart> carts = sparseToList();        PreferencesUtils.putString(mContext,CART_JSON,JSONUtil.toJSON(carts));    }    private List<ShoppingCart> sparseToList(){        int size = shoppingDatas.size();        System.out.println(size);        List<ShoppingCart> list = new ArrayList<>(size);        for (int i= 0;i<size;i++){            list.add(shoppingDatas.get(i));      //将栈中的数据按照从栈顶到栈底的顺序添加到List中        }        return list;                            //将list返回作为json数据保存到SharedPreferences中    }
从内存中读取出来的代码如下:
private void listToSparse(){        List<ShoppingCart> carts =  getDataFromLocal();  //从SharedPreferences中取出json数据        if(carts!=null && carts.size()>0){            for (ShoppingCart cart: carts) {                datas.put(cart.getId().intValue(), cart);  //将数据同时添加到栈以及稀疏数组中                shoppingDatas.push(cart);            }        }    }
public  List<ShoppingCart> getDataFromLocal(){        String json = PreferencesUtils.getString(mContext,CART_JSON);        System.out.println(json);        List<ShoppingCart> carts =null;        if(json !=null ){            carts = JSONUtil.fromJson(json,new TypeToken<List<ShoppingCart>>(){}.getType());//读取json数据        }        return  carts;    }
效果图如下所示:



0 0
原创粉丝点击