List subList()的一个demo

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

/**
 * Created by MyWorld on 2016/1/21.
 */
public class SubListDemoTest {

    @Test
    public void ListSizeShouldEquals1_WhenSourceList9Step5() {
        List<Integer> sourceList = new ArrayList<Integer>();
        for (int i = 0; i < 9; i++) {
            sourceList.add(i);
        }
        int step = 5;
        List<String> targetList = SubListDemo.split(sourceList, step);
        assertThat(targetList.size(), is(2));
    }

    @Test
    public void ListSizeShouldEquals2_WhenSourceList10Step5() {
        List<Integer> sourceList = new ArrayList<Integer>();
        for (int i = 0; i < 10; i++) {
            sourceList.add(i);
        }
        int step = 5;
        List<String> targetList = SubListDemo.split(sourceList, step);
        assertThat(targetList.size(), is(2));
    }

    @Test
    public void ListSizeShouldEquals3_WhenSourceList11Step5() {
        List<Integer> sourceList = new ArrayList<Integer>();
        for (int i = 0; i < 11; i++) {
            sourceList.add(i);
        }
        int step = 5;
        List<String> targetList = SubListDemo.split(sourceList, step);
        assertThat(targetList.size(), is(3));
    }

}
import java.util.ArrayList;
import java.util.List;

/**
 * Created by MyWorld on 2016/1/21.
 */
public class SubListDemo {
    public static List<String> split(List<Integer> list, int step) {
        List<String> listStr = new ArrayList<String>();
        int size = list.size();
        int times = size / step + (size % step == 0 ? 0 : 1);
        for (int i = 0; i < times; i++) {
            int fromIndex = i * step;
            int toIndex = (i + 1) * step;
            listStr.add(list.subList(fromIndex, (toIndex < size ? toIndex : size)).toString());
        }
        return listStr;
    }
}

tips:

java.util.List中有一个subList方法,用来返回一个list的一部分的视图。

List<E> subList(int fromIndex, int toIndex);

它返回原来list的从[fromIndex, toIndex)之间这一部分的视图,之所以说是视图,是因为实际上,返回的list是靠原来的list支持的。

所以,你对原来的list和返回的list做的“非结构性修改”(non-structural changes),都会影响到彼此对方。

所谓的“非结构性修改”,是指不涉及到list的大小改变的修改。相反,结构性修改,指改变了list大小的修改。

那么,如果涉及到结构性修改会怎么样呢?

如果发生结构性修改的是返回的子list,那么原来的list的大小也会发生变化;

而如果发生结构性修改的是原来的list(不包括由于返回的子list导致的改变),那么返回的子list语义上将会是undefined。在AbstractList(ArrayList的父类)中,undefined的具体表现形式是抛出一个ConcurrentModificationException。

因此,如果你在调用了sublist返回了子list之后,如果修改了原list的大小,那么之前产生的子list将会失效,变得不可使用。

tips: 如何删除一个list的某个区段,比如删除list的第2-5个元素?

方法是: 可以利用sublist的幕后还是原来的list的这个特性,比如

list.subList(from, to).clear();

这样就可以了。

示例代码:

public static void main(String[] args) {
        List<String> parentList = new ArrayList<String>();

        for(int i = 0; i < 5; i++){
            parentList.add(String.valueOf(i));
        }

        List<String> subList = parentList.subList(1, 3);
        for(String s : subList){
            System.out.println(s);//output: 1, 2
        }

        //non-structural modification by sublist, reflect parentList
        subList.set(0, "new 1");
        for(String s : parentList){
            System.out.println(s);//output: 0, new 1, 2, 3, 4
        }

        //structural modification by sublist, reflect parentList
        subList.add(String.valueOf(2.5));
        for(String s : parentList){
            System.out.println(s);//output:0, new 1, 2,    2.5, 3,    4
        }

        //non-structural modification by parentList, reflect sublist
        parentList.set(2, "new 2");
        for(String s : subList){
            System.out.println(s);//output: new 1, new 2
        }

        //structural modification by parentList, sublist becomes undefined(throw exception)
        parentList.add("undefine");
//        for(String s : subList){
//            System.out.println(s);
//        }
//        subList.get(0);
    }

一个很有趣的思考:如何最高效的实现一个list的split方法?

参见:http://stackoverflow.com/questions/379551/java-split-a-list-into-two-sub-lists

http://www.cnblogs.com/gaojing/archive/2012/06/17/java-list-sublist-caution.html

时间: 2024-10-12 20:42:35

List subList()的一个demo的相关文章

Flask---使用Bootstrap新建第一个demo

Flask---使用Bootstrap新建第一个demo 参考自http://www.jianshu.com/p/417bcbad82fb 还有<Flask web开发> 前端用到Bootstrap开源框架,Bootstrap是客户端框架,后台当然就是Flask了. 服务器需要做的只是提供引用了Bootstrap层叠样式表(CSS)和JS文件的html响应,并且在html.css和js代码中实例化需要的组件,这些操作的最理想的执行环境就是模板 关于模板的介绍及其实现原理:https://kb.

Node.js 的第一个 demo 和本地服务器配置

安装nodejs这里就不叙述了,直接上nodejs官网下载就好了,初学者建议直接下载安装版,无需自己去编译.nodejs安装版和安装其他软件一样,无门槛. 安装nodejs后启动node.js,会打开一个类似黑色的系统命令框,这里是直接输入js代码的命令框,因此在这里输入 node -v 会提示你没有 node 这个命令,如: 如果你想安装其他的包,如 express 等,就需要在开始菜单里面找到 Node.js command prompt 或者 直接运行 cmd 进入命令行. 进入命令行后,

Java学习 (一)、下载,配置环境变量,第一个demo

一.在 http://www.oracle.com 下载java JDK 安装到自定义的地方. 二.配置环境变量:在我的电脑→高级系统设置→环境变量 ① 找到Path新增一个路径(该路径为JDK存放的位置的bin,比如我放在D:\J2EE\JDK1.8.0\bin 下),两个路径之间要加分号隔开 ② 为了防止路径改变,可以新增一个变量,变量名自定义,变量值为JDK存放路径. 然后在Path 下新增一个路径为 %JAVA_HOME%\bin  即可. 保存后 运行(win+R) cmd 键入jav

如何看eclipse中的崩溃信息?用一个demo教会你

我相信很多android初学者用刚开始都是用的Eclipse开发工具,并且很多初级书籍也不会教大家怎么去看崩溃日志,虽然不难,但是靠自己琢磨还是挺浪费时间的,我们就写一个Demo来看看吧! 注释掉一行代码,让程序崩溃 注释掉创建ViewHolder对象的代码,让程序崩溃. MainActivity中展示一个ListView 这个Demo很简单,就是在MainActivity中展示一个ListView,<第一行代码>中的例子. 现在我们注释掉了创建ViewHolder对象的代码,连上手机,运行程

Android中Service的一个Demo例子

Android中Service的一个Demo例子  Service组件是Android系统重要的一部分,网上看了代码,很简单,但要想熟练使用还是需要Coding.  本文,主要贴代码,不对Service做过多讲解.  代码是从网上找的一个例子,Copy下来发现代码不完全正确,稍微修改了下.  AndroidManifest.xml <application android:icon="@drawable/ic_launcher" android:label="@stri

使用android的mediaplayer做成 一个demo,欢迎测试使用

附件是为一个定制视频产品而简单的写了一个demo,用来说明android的mediaplayer是如何使用的. http://files.cnblogs.com/guobaPlayer/palyerDemo3D.apk 欢迎下载测试. 完全采用androd的mediaplayer播放器api函数而编写. 锅巴视频工作室-----专业的移动设备视频客户端方案提供者 锅巴视频工作室,专注于android视频相关,蓝牙,wifi等软硬件项目的方案开发工作,欢迎联系:qq1852600324" 使用an

Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)

在android的应用层中,涉及到很多应用框架,例如:Service框架,Activity管理机制,Broadcast机制,对话框框架,标题栏框架,状态栏框架,通知机制,ActionBar框架等等. 下面就来说说经常会使用到通知机制中的通知栏框架(Notificaiton),它适用于交互事件的通知.它是位于顶层可以展开的通知列表.它会时不时的提醒你什么软件该更新了,什么人发你微信消息了等. (网上看了下,全面介绍的文章不多,所以就萌生了写这篇的念头,随便当作回顾笔记.下面我就通过官方文档.源代码

Android 通知栏Notification的整合 全面学习 (一个DEMO让你全然了解它)

在android的应用层中.涉及到非常多应用框架.比如:Service框架,Activity管理机制,Broadcast机制.对话框框架.标题栏框架,状态栏框架.通知机制,ActionBar框架等等. 以下就来说说常常会使用到通知机制中的通知栏框架(Notificaiton).它适用于交互事件的通知.它是位于顶层能够展开的通知列表. 它会时不时的提醒你什么软件该更新了,什么人发你微信消息了等. (网上看了下,全面介绍的文章不多,所以就萌生了写这篇的念头.随便当作回想笔记. 以下我就通过官方文档.

初识nginx之第一个demo

商城项目做了一个多月了,想到必须用到负载均衡,简单了解了一下nginx,首先分享第一个demo,五月份上线后,会继续分享一系列相关知识. 在nginx根目录下,用了一个园友的批处理文件nginx.bat,用于启动和关闭nginx服务.需要nginx1.9.3的园友尽管留下邮箱,带批处理文件的压缩包会及时分享给你的. 我分别在ip为xxx和xxx的服务器下部署了三个站点,第一台服务器用了8040(site1),8041端口(site2),  第二台服务器用了8043(site3)端口,,负载均衡服