Android遍历对象包含自身集合的算法

2020-11-22  本文已影响0人  奔跑的佩恩

前言

Android开发过程中,我们经常会遇到遍历整个集合的情况。但是在我们接收服务端返回数据json串的结构有种特别的情况,那就是对象种包含有一个集合,集合中装的数据类型又是自己,且数据层级不确定的情况,面对这种数据结构我们要怎样才能将其遍历完呢?

今天涉及内容:

  1. 涉及到的依赖
  2. 数据结构特点
  3. 拼接具有该特性的json
  4. 该数据结构全遍历在Activty中的使用
  5. 效果图和项目结构图
  6. MainHelper源码

先来波效果图


1.gif

一.涉及到的依赖

由于涉及到数据的组装与解析,所以会使用到json解析的问题。这里我采用的是Gson解析,则需要在app_module对应的build.gradle中添加gson依赖:

dependencies {
    //gson
    implementation 'com.google.code.gson:gson:2.8.5'
    //其他代码省略
    //......
}

二.数据结构特点

先来介绍下需要遍历的数据结构类型。
整个数据是一个对象集合。单个的对象中有些不同的属性,除此以外,该对象中会包含一个集合,该集合可能有数据,也可能没有。如果有数据的话,那么此集合中装的数据也是该对象本身。说起来有点绕,以Book为例说明,则简单的说来,我们就是要遍历一个集合中的所有Book对象,下面贴出Book代码:

public class Book {

    private String name;
    private int page;
    private List<Book>data;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public List<Book> getData() {
        return data;
    }

    public void setData(List<Book> data) {
        this.data = data;
    }

}

这里的难点是,Book中含有List<Book>data,而data中装载的还是Book,只要data不为null,我们就得一直遍历下去,直到获取所有的Book对象。
该数据结构最大的难点在于:Book 的数据层级未知,有多少则需要遍历多少

三.拼接具有该特性的 json 串

为了详细讲解这个问题,我们需要组装一个该特色的Json串。
接下来我会组装一个Book的集合,里面有三个Book对象(以下Book对象item表示),为了模拟item数据层级的不确定性,我会将每个item设置不同的层级结构。

3.1 第一个 item 特点

第一个 item层级为2,第二层有3个item,组装该item的代码如下:

    /***
     * 第一个book总item个数:1*3=3
     *
     * @return
     */
    public Book getFirstItem(){
        Book book=new Book();
        book.setName("first,第一层");
        book.setPage(1);
        List<Book> firstList= new ArrayList();
        for(int i=0;i<3;i++){
            Book book2=new Book();
            book2.setName("first"+i+",第二层");
            book2.setPage(1*10+(i+1));
            firstList.add(book2);
        }
        book.setData(firstList);
        return book;
    }
3.2 第二个 item 特点

第二个item我们设置数据层级为一层,比较简单。

    /***
     * 第二个book总item个数:1*1=1
     *
     * @return
     */
    public Book getSecondItem(){
        Book book=new Book();
        book.setName("second,第一层");
        book.setPage(2);
        return book;
    }
3.3 第三个 item 特点

第三个 item 会比较复杂。第一层item下面会有2个item,第二层下面有2个item,第三层下面有2个item,到第四层时,当item下标为1时,下面又有2个item。即第三个item共有5层。组装第三个 item的代码如下:

    /***
     * 第三个book总item个数:1*2*2*(1+1*2)=12
     *
     * @return
     */
    public Book getThirdItem(){
        Book book=new Book();
        book.setName("third,第一层");
        book.setPage(3);
        List<Book>thirdList= new ArrayList();
        for(int i=0;i<2;i++){
            Book book2=new Book();
            book2.setName("third"+i+",第二层");
            book2.setPage(3*10+(i+1));
            List<Book>third2List= new ArrayList();
            for(int j=0;j<2;j++) {
                Book book3 = new Book();
                book3.setName("third"+i + j + ",第三层");
                book3.setPage(3 * 100 + (j+1));
                List<Book>third3List= new ArrayList();
                for(int k=0;k<2;k++){
                    Book book4 = new Book();
                    book4.setName("third" + i + j +k + ",第四层");
                    book4.setPage(3 * 1000 + (k+1));
                    if(k==1){
                        List<Book>third4List= new ArrayList();
                        for(int f=0;f<2;f++){
                            Book book5 = new Book();
                            book5.setName("third" +i + j +k + f + ",第五层");
                            book5.setPage(3 * 10000 + (f+1));
                            third4List.add(book5);
                        }
                        book4.setData(third4List);
                    }
                    third3List.add(book4);
                }
                book3.setData(third3List);
                third2List.add(book3);
            }
            book2.setData(third2List);
            thirdList.add(book2);
        }
        book.setData(thirdList);
        return book;
    }

然后将这三个item添加到bookList中:

        List<Book> bookList = new ArrayList<>();
        //第一个item
        Book firstItem = mainHelper.getFirstItem();
        bookList.add(firstItem);
        //第二个item
        Book secondItem = mainHelper.getSecondItem();
        bookList.add(secondItem);
        //第三个item
        Book thirdItem = mainHelper.getThirdItem();
        bookList.add(thirdItem);

        //将list转json串
        String jsonString = mainHelper.BeanToString(bookList);
        LogUtil.i("jsonString:"+jsonString);

生成的json结构如下图

数据.png
结构.png
以上只是截取部分数据图,具体的大家可以查看运行打印的json串
[{"data":[{"name":"first0,第二层","page":11},{"name":"first1,第二层","page":12},{"name":"first2,第二层","page":13}],"name":"first,第一层","page":1},{"name":"second,第一层","page":2},{"data":[{"data":[{"data":[{"name":"third000,第四层","page":3001},{"data":[{"name":"third0010,第五层","page":30001},{"name":"third0011,第五层","page":30002}],"name":"third001,第四层","page":3002}],"name":"third00,第三层","page":301},{"data":[{"name":"third010,第四层","page":3001},{"data":[{"name":"third0110,第五层","page":30001},{"name":"third0111,第五层","page":30002}],"name":"third011,第四层","page":3002}],"name":"third01,第三层","page":302}],"name":"third0,第二层","page":31},{"data":[{"data":[{"name":"third100,第四层","page":3001},{"data":[{"name":"third1010,第五层","page":30001},{"name":"third1011,第五层","page":30002}],"name":"third101,第四层","page":3002}],"name":"third10,第三层","page":301},{"data":[{"name":"third110,第四层","page":3001},{"data":[{"name":"third1110,第五层","page":30001},{"name":"third1111,第五层","page":30002}],"name":"third111,第四层","page":3002}],"name":"third11,第三层","page":302}],"name":"third1,第二层","page":32}],"name":"third,第一层","page":3}]

四.该数据结构全遍历在Activty中的使用

数据结构已经组装完成,则我们需要遍历的是bookList中的所有Book对象。我们很容易想到的是用递归思想遍历完所有book,这里为了使用方便,我已经将模拟数据的组装及递归遍历的方法都写在了MainHelper类中,下面就来看看MainHelper遍历bookList中的所有Book对象在MainActivity中的使用吧。

public class MainActivity extends AppCompatActivity {

    private TextView mTv;
    private Button mBtn;

    private MainHelper mainHelper;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LogUtil.setDebug(true);

        initView();
        initData();
        setListener();
    }

    private void initView() {
        mTv = findViewById(R.id.tv);
        mBtn = findViewById(R.id.btn);
    }

    private void initData() {
        mainHelper=new MainHelper();
    }

    private void setListener() {
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createData();
            }
        });
    }

    private void createData() {
        List<Book> bookList = new ArrayList<>();
        //第一个item
        Book firstItem = mainHelper.getFirstItem();
        bookList.add(firstItem);
        //第二个item
        Book secondItem = mainHelper.getSecondItem();
        bookList.add(secondItem);
        //第三个item
        Book thirdItem = mainHelper.getThirdItem();
        bookList.add(thirdItem);

        //将list转json串
        String jsonString = mainHelper.BeanToString(bookList);
        LogUtil.i("jsonString:"+jsonString);


        //遍历所有item
        List<Book> totalList=mainHelper.getTotalList(bookList);

        StringBuffer buffer=new StringBuffer();
        LogUtil.i("=======size=="+totalList.size());
        buffer.append("集合总个数: size="+totalList.size()+"\n");
        for(int i=0;i<totalList.size();i++){
            LogUtil.i("=====i="+i+"   bookName="+totalList.get(i).getName());
            buffer.append(totalList.get(i).getName()+"\n");
        }
        mTv.setText(buffer.toString());
    }

}

综合前面3个item的组装分析,我们可以发现bookList中总共包含的book个数为:
1*3+1*1+1*2*2*(1+1*2)=16,最后遍历totalList发现其个数即为16,说明算法正确。

五.效果图和项目结构图

效果图.gif 项目结构图.png

六.MainHelper源码

下面贴出MainHelper源码:

上一篇下一篇

猜你喜欢

热点阅读