项目实战:滚动刷新场景(从ArrayList到LinkedList)

Posted 由此及彼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目实战:滚动刷新场景(从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 类还为在列表的开头及结尾getremoveinsert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列双端队列

此类实现 Deque 接口,为 addpoll 提供先进先出队列操作,以及其他堆栈和双端队列操作。

所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。


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)的主要内容,如果未能解决你的问题,请参考以下文章

使用单击 Spinner 项刷新 ArrayList 以将新数据显示到 RecyclerView

python实战项目练习-Django商城项目之注册功能实现

IDEA中Git实战

在IDEA中实战Git

使用keepAlive对上下拉刷新列表数据 和 滚动位置细节处理 - vue

better-scroll插件的实战