常用Iterator遍历,筛选小记

本文介绍了Java中使用Iterator遍历集合的示例,包括Person、Card和TestForeach类的应用。强调了在使用Iterator时不能直接通过集合进行add或remove操作,而应使用iterator.remove(),并指出此方法适用于单线程环境。在多线程中,尝试使用iterator.remove()会导致'ConcurrentModificationException'。同时,将ArrayList替换为并发容器CopyOnWriteArrayList会抛出'UnsupportedOperationException',因为此类不支持remove操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面给个示例
class类:Person,Card, TestForeach 共三个
Person:property有姓名,卡片 两个属性
Card:property 有cardCode 1个属性
TestForeach:主测试类

Person代码

public class Person {
    private String username;  //小朋友姓名
     private List<Card> cardList=new ArrayList<Card>(); // 卡片

	public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

   
    public List<Card> getCardList() {
        return cardList;
    }

    public void setCardList(List<Card> cardList) {
        this.cardList = cardList;
    }
}

Card代码

public class Card {
    private String cardCode;
  
    public String getCardCode() {
        return cardCode;
    }

    public void setCardCode(String cardCode) {
        this.cardCode = cardCode;
    }
}

TestForeach 测试类代码

@Slf4j
public class TestForeach {
    public static void main(String[] args) {
        Person person = new Person();
        Card card = new Card();
        card.setCardName("card1");
        card.setCardCode("1");
        Card card1 = new Card();
        card1.setCardCode("2");
        card1.setCardName("card2");
        person.getCardList().add(card);
        person.getCardList().add(card1);
        Card card2 = new Card();
        card1.setCardCode("3");
        card1.setCardName("card3");
        person.getCardList().add(card);
        person.getCardList().add(card1);
        person.getCardList().add(card2);
        log.info("现在的card集合是 {}",JSON.toJSONString(person.getCardList()));
// 1: 使用Iterator进行遍历
        Iterator iterator = person.getCardList().iterator();
        while (iterator.hasNext()) {
            Card c = (Card) iterator.next();
            log.info("当前遍历进来的元素 {}", JSON.toJSONString(c)); //打印每一次遍历过来的元素
            if ("1".equals(c.getCardCode())) {
                iterator.remove();
            }
        }
        log.info("最后过滤后的集合元素",JSON.toJSONString(person.getCardList()))

//2:通过 集合的 removeIf 方法结合lambda表达式进行过滤,排除cardCode为:2的card对象
        person.getCardList().removeIf(card4 -> "2".equals(card4.getCardCode()));
         log.info("removeIf方法排除后的{}", JSON.toJSONString(person.getCardList()));
      //3:通过filter方法过滤,查找出cardCode为:3的card对象
        List<Card> cardList = person.getCardList().stream().filter(card5 -> "3".equals(card5.getCardCode())).collect(Collectors.toList());
        log.info("第三次打印{}", JSON.toJSONString(cardList));
//      log.info("第三次打印{}", JSON.toJSONString(person.getCardList()));

//4:forEach方法进行遍历
        List<Card> cardList = person.getCardList();
        for (Card card6:cardList) {
            System.out.println(JSON.toJSONString(card6));
        }
// 5:集合的forEach方法进行遍历        
        cardList.forEach(card7 -> System.out.println(JSON.toJSONString(card7)));
    }
}

使用“::”来访问类中的方法
JDK8中的双冒号的用法,就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。

  List<Card> cardList = person.getCardList();
        for (Card card3:cardList) {
            System.out.println(card3);
        }
// 上面的代码跟下面的代码等价
  List<Card> cardList = person.getCardList();
    cardList.forEach(System.out::println);
    
// 上面的代码跟下面的代码等价
 List<Card> cardList = person.getCardList();
    cardList.forEach(card5->{
    System.out.println(card5);
    });
//上面的代码跟下面的代码等价
Consumer<String> methodParam = System.out::println; //方法参数
        cardList.forEach(card6 -> methodParam.accept(card6));

注意一点:使用iterator 进行遍历的时候,不能直接操作集合(List,Vector)的add 或者remove操作。因为通过迭代器的remove方法进行操作。

 @Test
    public void testIterator() {
        List<String> memberList = Lists.newArrayList();
        memberList.add("hxy");
        memberList.add("tf");
        memberList.add("hhp");
        for (Iterator iterator = memberList.iterator(); iterator.hasNext(); ) {
//            String string = (String) iterator.next();
            if ("hxy".equals(iterator.next())) {
//                memberList.remove("hxy");// 调用arrayList 上的remove方法的时候,就会出现“ConcurrentModificationException”异常因为此时ArrayList上的modCount 和iterator 上的expectedModCount不一致,会抛出异常
                iterator.remove();// 该方法在调用iterator 的remove,也会调用arrayList 中的remove方法。两对象的modCount和expectedModCount一致。
            }
        }
        System.err.println(memberList);  // 打印的是去除掉"hxy"的list集合
    }

还有iterator.remove()方法试用于单线程,当出现多线程时,会报错“ConcurrentModificationException”。如下代码。

参考文档:https://www.cnblogs.com/dolphin0520/p/3933551.html

public class ThreadTest {
    static List<Integer> list = new ArrayList<>();

    public static void main(String[] args) {
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        Thread thread1 = new Thread() { // 开启第一个线程
            public void run() {
                Iterator<Integer> iterator = list.iterator();
                while (iterator.hasNext()) {
                    Integer integer = iterator.next();
                    System.out.println(integer);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        Thread thread2 = new Thread() {  // 开启第二个线程
            public void run() {
                Iterator<Integer> iterator = list.iterator();
                while (iterator.hasNext()) {
                    Integer integer = iterator.next();
                    if (integer == 2)
                        iterator.remove();
                }
            }
        };
        thread1.start();
        thread2.start();
    }
}

当我们把ArrayList替换成并发容器 CopyOnWriteArrayList时,也是会报错。“UnsupportedOperationException”。

static List<Integer> list = new CopyOnWriteArrayList<>();

查看CopyOnWriteArrayList#remove方法可知:该类不支持remove操作,当调用remove方法时,会直接抛出异常。

  public void remove() {
            throw new UnsupportedOperationException();
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值