首页 > 代码库 > 项目实战:滚动刷新场景(从ArrayList到LinkedList)
项目实战:滚动刷新场景(从ArrayList到LinkedList)
如果有这样一个需求,有这样一个列表显示数据,现假设一共显示25项,初始状态为空。
首先从0-24添加数据,满了之后,覆盖最早数据,即继续从0-24追加数据。
习惯性思维ArrayList开始搞。
java.util
类 ArrayList<E>
java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.ArrayList<E>
- 所有已实现的接口:
- Serializable,Cloneable,Iterable<E>,Collection<E>,List<E>,RandomAccess
- 直接已知子类:
- AttributeList,RoleList,RoleUnresolvedList
Duang的一下写好代码,不就是add嘛。
import java.util.ArrayList; import java.util.List; /* * 权兴权意-20160920 */ public class ArrayListTest { <span style="white-space:pre"> </span>private static List<Integer> list = new ArrayList<Integer>(); <span style="white-space:pre"> </span>private static int count = 0; public static void main(String[] args) { // TODO Auto-generated method stub for(int i = 0;i <= 50;i++){ list.add(count,count); count++; if (count == 25) count = 0; for(int temp : list){ System.out.print(temp + ","); } System.out.println("-----+" + count); } } }
看一下效果,然而并没有这么简单,
阴影部分初始化数据木有问题,看阴影部分下方,从0-24添加数据也木有问题,不过,你有木有发现,List越来越长了,现在我们先看看看API,到底是什么鬼。
public class ArrayList<E>
- extends AbstractList<E>
- implements List<E>, RandomAccess, Cloneable, Serializable
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null 在内的所有元素。除了实现List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于Vector 类,除了此类是不同步的。)
随着向 ArrayList 中不断添加元素,其容量也自动增长。
继续查看API,发现了这个:add
public void add(int index,
E element)
- 将指定的元素插入此列表中的指定位置。向右移动当前位于该位置的元素(如果有)以及所有后续元素(将其索引加 1)。
- 指定者:
- 接口
List<E>
中的add
- 覆盖:
- 类
AbstractList<E>
中的add
- 参数:
index
- 指定元素所插入位置的索引element
- 要插入的元素- 抛出:
IndexOutOfBoundsException
- 如果索引超出范围 (index < 0 || index > size())
set
public E set(int index,
E element)
- 用指定的元素替代此列表中指定位置上的元素。
- 指定者:
- 接口
List<E>
中的set
- 覆盖:
- 类
AbstractList<E>
中的set
- 参数:
index
- 要替代的元素的索引element
- 存储在指定位置上的元素- 返回:
- 以前位于该指定位置上的元素
- 抛出:
IndexOutOfBoundsException
- 如果索引超出范围 (index < 0 || index >= size())
所以说要多读API,第一轮初始化数据用add,第二轮应该是set更新数据。
即先判断这个位置是否为空,为空add否则set。
duang~又写好了。
import java.util.ArrayList; import java.util.List; /* * 权兴权意-20160920 */ public class ArrayListTest { private static List<Integer> list = new ArrayList<Integer>(); <span style="white-space:pre"> </span>private static int count = 0; public static void main(String[] args) { // TODO Auto-generated method stub for(int i = 0;i <= 50;i++){ if(list.get(i) == null){ list.add(count,count); }else{ list.set(count,count*10); } count++; if (count == 25) count = 0; for(int temp : list){ System.out.print(temp + ","); } System.out.println("-----+" + count); } } }
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at com.car.quan.List.ArrayListTest.main(ArrayListTest.java:19)
get(i)越界异常,为空时怎么能获取第0个元素呢?
get
public E get(int index)
- 返回此列表中指定位置上的元素。
- 指定者:
- 接口
List<E>
中的get
- 指定者:
- 类
AbstractList<E>
中的get
- 参数:
index
- 要返回元素的索引- 返回:
- 此列表中指定位置上的元素
- 抛出:
IndexOutOfBoundsException
- 如果索引超出范围 (index < 0 || index >= size())
难道还不能判空了吗?
看一下数字规律,Index: 0 = Size: 0,此时是第一轮初始化数据,get思路:list.size() == count。
import java.util.ArrayList; import java.util.List; /* * 权兴权意-20160920 */ public class ArrayListTest { private static List<Integer> list = new ArrayList<Integer>(); private static int count = 0; public static void main(String[] args) { // TODO Auto-generated method stub for(int i = 0;i <= 50;i++){ if(list.size() == count){ list.add(count,count); }else{ list.set(count,count*10); } count++; if (count == 25) count = 0; for(int temp : list){ System.out.print(temp + ","); } System.out.println("-----+" + count); } } }
由此实现滚动刷新的效果。
不过,滚动刷新,刷掉最早的数据,有木有一种先进先出的feel,队列,get。
队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
在队列这种数据结构中,最先插入的元素将是最先被删除的元素;反之最后插入的元素将是最后被删除的元素,因此队列又称为“先进先出”(FIFO—first in first out)的线性表。
在java5中新增加了java.util.Queue接口,用以支持队列的常见操作。该接口扩展了java.util.Collection接口。
Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用element()或者peek()方法。
值得注意的是LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。
java.util
类 LinkedList<E>
java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.AbstractSequentialList<E> java.util.LinkedList<E>
- 类型参数:
E
- 在此 collection 中保持的元素的类型
- 所有已实现的接口:
- Serializable,Cloneable,Iterable<E>,Collection<E>,Deque<E>,List<E>, Queue<E>
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾get、remove 和insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
offer
public boolean offer(E e)
- 将指定元素添加到此列表的末尾(最后一个元素)。
- 指定者:
- 接口
Deque<E>
中的offer
- 指定者:
- 接口
Queue<E>
中的offer
- 参数:
e
- 要添加的元素- 返回:
- true(根据
Queue.offer(E)
的规定) - 从以下版本开始:
- 1.5
poll
public E poll()
- 获取并移除此列表的头(第一个元素)
- 指定者:
- 接口
Deque<E>
中的poll
- 指定者:
- 接口
Queue<E>
中的poll
- 返回:
- 此列表的头,如果此列表为空,则返回 null
- 从以下版本开始:
- 1.5
接下来就是水到渠成的事。
import java.util.LinkedList; import java.util.List; import java.util.Queue; /* * 权兴权意-20160920 */ public class QueueTest { private static List<Integer> q = new LinkedList<Integer>(); public static void main(String[] args) { for(int i = 1;i <= 50;i++){ ((LinkedList<Integer>) q).offer(i); if (q.size() == 26) ((LinkedList<Integer>) q).poll(); for(int temp : q){ System.out.print(temp + ","); } System.out.println("------------------"); } } }
小结:熟练API,熟练数据结构,Android项目开发之源还在JavaSE。
题外话:
队列是一种数据结构.它有两个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个慢,则第二个线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个线程集赶上来。
项目实战:滚动刷新场景(从ArrayList到LinkedList)