记一次关于列表删除元素的感悟

26 篇文章 0 订阅
26 篇文章 0 订阅

Android列表中元素的增加和删除

1.列表增加元素需要注意:

//局部刷新
mJokeAdapter.notifyItemInserted(int)
//只会更新从positionStart开始的itemCount的个数据变化,而之前的view和数据是不会发生变化的。
mJokeAdapter.notifyItemRangeInserted(positionStart, data.size)

2.列表中删除元素需要注意:

list.remove(i);
notifyItemRemoved(i);
//只会更新从positionStart开始的itemCount的个数据变化,而之前的view和数据是不会发生变化的。
notifyItemRangeChanged(i, list.size() - 1);

3.使用ListAdapter增加元素和删除元素:

//直接传入最新的元素进去
listAdapter.submitList(mList);
//增加元素就是:notifyItemRangeChanged(i, list.size() - 1);
notifyItemRemoved(i);
notifyItemRangeChanged(i, list.size() - 1);  


4.解决更新数据的时候,列表的Item出现闪烁的问题:

01.使用局部刷新


 //局部刷新
 adapter.notifyItemChanged(position);
 

02.设置adapter的属性


//绑定adapter给RecycleView之前,设定adapter的stableIds为true
adapter.setHasStableIds(true);

03.给Item的position标记tag


    @Override
    public long getItemId(int position) {
        return position;
    }


5.列表删除元素的实例,逐个删除、批量删除:

01.逐个删除,调用列表的remove()方法,注意使用局部刷新notifyItemRemoved(i):

    fun removeData(position: Int) {
        list.removeAt(position)
        notifyItemRemoved(position)
        notifyItemChanged(0, list.size)
    }

02.需要批量删除集合中的元素,集合的索引会在每一次删除元素的时候发生改变,因此需要及时改变索引值(否则会出现删除错乱的情况)

方案一:

                //循环删除列表的元素,从后往前删,这样会动态改变集合的索引值,完美批量删除元素
                for (int i = list.size() - 1; i >= 0; i--) {
                    //判定条件
                    if (tMap.get(i)) {
                        Log.i("hy55", "i = " + i);
                        Toast.makeText(this, "haha", Toast.LENGTH_SHORT).show();
                        list.remove(i);
                    }
                }
                //删除元素之后将新的列表传到RecyclerView之后
                adapter.setData(list);

然后在Adapter中创建列表赋值的方法

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    private Context mContext;
    private List<String>list;
    private HashMap<Integer, Boolean> maps = new HashMap<Integer, Boolean>();//保存列表中每个item的选中状态
    public RecyclerViewOnItemClickListener onItemClickListener;

    public RecyclerViewAdapter(Context mContext, List<String> list) {
        this.mContext = mContext;
        this.list = list;
        initMap();
    }

    //重新设置列表中的值
    public void setData(List<String> list) {
        this.list = list;
        notifyDataSetChanged();
        initMap();
    }

方案二:

                //使用迭代器,推荐
                Iterator<String> itr = list.iterator();
                while (itr.hasNext()) {
                    if (//TODO: 判定条件)
                    itr.remove();
                }

6.列表去重的方法:

01.创建数据类

//data class官网介绍:https://kotlinlang.org/docs/data-classes.html
data class bean(
    val name: String? = null,
    val sex: String? = null
) {
    //默认的equals()和hashCode()方法会比较所有的属性
    //如果你重新定义了equals()和hashCode()方法,那么你设置的主键参数绝对不能为空,否则就会出现remove()方法删除不掉指定对象的情况
    override fun equals(other: Any?): Boolean {
        val bean = other as bean
        //使用name作为判断addressListBean是否相同的元素
        //使用name和sex都作为主键,那么只要两个参数都相等,这两个元素才相等
//        return name == bean.name
        return (name == bean.name && sex == bean.sex)
    }

    override fun hashCode(): Int {
        return name.hashCode()
    }
}

02.列表去重的逻辑

class MainActivity : AppCompatActivity() {

    //创建一个存储数据的列表
//    private var tempList: MutableList<bean> = mutableListOf()
    private var tempList = ArrayList<bean>()

    private var curList = ArrayList<bean>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main);
        tempList.add(bean("aex", "girl", age = "12"))
        curList.add(bean(age = "12"))
        curList.add(bean(age = "13"))

        findViewById<Button>(R.id.btn1).setOnClickListener {
            Log.d("hy55", "删除之前tempList的值:$tempList")
            Log.d("hy55", "curList:$curList")

            //两个列表删除相同的元素
            //错误:for (i in 0 until tempList.size)[for (i in tempList.indices)]:这种写法i会从0增加到2,但最后tempList的长度已经是1了,就会报错
//            for (i in tempList.size - 1 downTo 0) {
//                for (j in 0 until curList.size) {
//                    Log.i("hy55", "tempList.size=${tempList.size}、i=$i")
//                    if (curList[j].age == tempList[i].age) {
//                        tempList.removeAt(i)
//                        break
//                    }
//                }
//            }

//            //两个列表删除相同的元素,使用迭代器,迭代器索引的起始位置是头元素的前面,所以iterator.next()就是列表的第一个元素
//            val iterator = tempList.iterator()
//            while (iterator.hasNext()) {
//                val s = iterator.next()
//                for (j in 0 until curList.size) {
//                    Log.i("hy55", "tempList.size=${tempList.size}")
//                    Log.i("hy55", "curList[j].age=${curList[j].age}")
//                    Log.i("hy55", "s.age=${s.age}")
//                    //如果for循环结束,没有满足条件的,for循环也会break
//                    if (curList[j].age == s.age) {
//                        //直接删除该索引下的值,tempList直接调用remove()方法删除了该元素,
//                        iterator.remove()
//                        //break退出for循环,因为删除元素的目的已经实现了,
//                        // 继续遍历,如果后续curList中还有满足条件的,但是该iterator已经remove()掉了,重复remove()就会报错
//                        break
//                    }
//                }
//            }


            //两个列表删除相同的元素
//            val list = ArrayList<bean>()
//
//            for (i in 0 until tempList.size) {
//                var flag = false
//                for (j in 0 until curList.size) {
//                    //如果tempList中的元素和curList重叠了,那么就不会添加这个元素
//                    if(tempList[i].age == curList[j].age) {
//                        flag = true
//                        break
//                    }
//                }
//                if(!flag) {
//                    list.add(tempList[i])
//                }
//            }
//            Log.d("hy55", "list:$list")

            //两个列表,删除相同元素,通过打印可以看出forEach{}的原理就是从前往后遍历列表
            curList.forEach{ it1 ->
                Log.d("hy55", "it1=$it1")
                for(i in tempList.size - 1 downTo 0) {
                    Log.d("hy55", "i=$i")
                    if(tempList[i].age == it1.age) {
                        tempList.removeAt(i)
                        Log.d("hy55", "tempList.size=${tempList.size}")
                    }
                }
            }


            //删除所有的指定元素,只需要指定主键,列表会认为bean(name = "aex")和bean("aex", "girl")、bean("aex", "boy")相等
//            for(i in 0 until tempList.size){
//                tempList.remove(bean(name = "aex"))
//            }

            //改变某个元素的状态
//            for(i in 0 until tempList.size){
//                if (tempList[i].name == "tom"){
//                    tempList[i].sex = "girl"
//                }
//            }

            //直接删掉第一个符合条件的元素,后面还有重复的元素也不会被删除,只有指定了主键,列表才会认为bean(name = "aex")和bean("aex", "girl")、bean("aex", "boy")相等
//            tempList.remove(bean(name = "aex"))

            //删除后面的重复元素,如果有重复的元素,保留前面的元素,删除后面的元素
//            for(i in (tempList.size - 1) downTo 1){
//                if(tempList[i].name == "aex") {
//                    tempList.removeAt(i)
//                }
//            }

            //删除后面的重复元素,如果有重复的元素,保留前面的元素,删除后面的元素
//            for(i in 0 until tempList.size){
//                for (j in tempList.size - 1 downTo 1) {
//                    if(tempList[i].name == tempList[j].name) {
//                        Log.d("hy55", "$i、$j")
//                        //相当于tempList.remove(name = "aex"),直接删除第一个元素
                        tempList.remove(tempList[j])
//                        tempList.removeAt(j)
//                        Log.d("hy55", "删除之后tempList的值:$tempList")
//                    }
//                }
//            }

            //删除后面的重复元素,如果有重复的元素,保留前面的元素,删除后面的元素
//            for(i in 0 until tempList.size){
//                for (j in i + 1 until  tempList.size) {
//                    //只要主键相等,那么这两个元素就是相等的
//                    if(tempList[i].name == tempList[j].name) {
//                        Log.d("hy55", "$i、$j")
//                        //相当于tempList.remove(name = "aex"),直接删除第一个元素
                        tempList.remove(tempList[j])
//                        tempList.removeAt(j)   //removeAt(j)是删除指定位置的元素,是可以生效的
//                        Log.d("hy55", "删除之后tempList的值:$tempList")
//                    }
//                }
//            }

            //使用迭代器,删除所有的元素,原理是下标索引遍历,迭代器索引的起始位置是头元素的前面,所以iterator.next()就是列表的第一个元素
//            val iter = tempList.iterator()
//            while (iter.hasNext()) {
//                val s = iter.next()
//                //Log.i("hy55", "s1=${iter.next().age}"),此处崩溃的原因是iter.next()就会触发索引后移,
//                // 前面(或者后面)已经有iter.next(),在log中的iter.next()也会触发索引后移,导致NoSuchElementException,索引超出了元素的长度
//                if(s.age == "12") {
//                    iter.remove()
//                }
//            }

            Log.d("hy55", "删除之后tempList的值:$tempList")
        }

        findViewById<Button>(R.id.btn2).setOnClickListener {
            Log.d("hy55", "增加之前tempList的值:$tempList")
            tempList.add(bean("tom", "boy"))
            tempList.add(bean("aex", "boy", "13"))
            Log.d("hy55", "增加之后tempList的值:$tempList")
        }

    }
}

03.布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn1"
        android:text="删除"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn2"
        android:text="增加"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="@+id/btn1"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>

4.ArrayList的remove()方法源码,remove()方法自带循环遍历过程

    public boolean remove(Object o) {
        if (o == null) {
            //循环遍历
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            //循环遍历
            for (int index = 0; index < size; index++)
                //使用equals()方法比较对象是否相等
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            //创建一个新的集合,去掉需要删除的元素
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }
    
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值