同一个迭代器一只能迭代一次

一、简单说明

同一个迭代器只能迭代一次,这里我不细说,可以参考这个:
https://blog.csdn.net/weixin_46351306/article/details/113705527

二、功能要求

今天和同事看了一个问题,大概问题如下:
解析yaml文件,并能实现对yaml文件内容进行更改。

三、实现

2.1 引入依赖

<dependency>
      <groupId>org.yaml</groupId>
      <artifactId>snakeyaml</artifactId>
      <version>1.21</version>
</dependency>

这是一个可以解析yaml文件内容的包,将yaml的字符串转换为对象,也可将响应的对象转换为字符串。

2.2 相关代码

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.util.Iterator;

public class Test {

    //更新YAML配置
    public void updYamlCfg() {
    	
    	//yaml字符串
        String yamlContent = "";

        DumperOptions dumperOptions = new DumperOptions();
        dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        dumperOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
        dumperOptions.setPrettyFlow(false);
        Yaml yaml = new Yaml(dumperOptions);
		
		//将yaml转换为对象迭代器
        Iterable<Object> objects = yaml.loadAll(yamlContent);

		//对yaml对象内容做更改
        for (Object object : objects) {
			//略
        }

		//将更改后的迭代器内容转换为字符串
        String newYamlContent2 = yaml.dumpAll(objects.iterator());
        System.out.println(newYamlContent2);
    }
}

上述代码实现的功能:
1、将读取到的字符串yaml转换为对象
2、对yaml对象内容进行更改
3、将修改后的对象重新转换为yaml

一开始看到用增强for遍历迭代器,还感觉挺奇怪的,于是点开了编译后的代码看了下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

import java.util.Iterator;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.DumperOptions.ScalarStyle;

public class Test {
    public Test() {
    }

    public void updYamlCfg() {
        String yamlContent = "";
        DumperOptions dumperOptions = new DumperOptions();
        dumperOptions.setDefaultFlowStyle(FlowStyle.BLOCK);
        dumperOptions.setDefaultScalarStyle(ScalarStyle.PLAIN);
        dumperOptions.setPrettyFlow(false);
        Yaml yaml = new Yaml(dumperOptions);
        Iterable<Object> objects = yaml.loadAll(yamlContent);

        Object var8;
        for(Iterator var7 = objects.iterator(); var7.hasNext(); var8 = var7.next()) {
        }

        String newYamlContent2 = yaml.dumpAll(objects.iterator());
        System.out.println(newYamlContent2);
    }
}

原来自动转成了迭代器,不是重点,不关注。

四 、问题出现

按上述逻辑来看,看似没问题,但是运行结果发现,输出为空字符。

最后,点开了dumpAll的源码看到:

    private void dumpAll(Iterator<? extends Object> data, Writer output, Tag rootTag) {
        Serializer serializer = new Serializer(new Emitter(output, this.dumperOptions), this.resolver, this.dumperOptions, rootTag);

        try {
            serializer.open();

            while(data.hasNext()) {
                Node node = this.representer.represent(data.next());
                serializer.serialize(node);
            }

            serializer.close();
        } catch (IOException var6) {
            throw new YAMLException(var6);
        }
    }

调用了同一个迭代器的data.hasNext()方法,且一直为false,故此,每次执行更新yaml内容之后,再想输出修改后的对象内容,就总是为空字符串。

五、小结

大家都知道同一个迭代器只能迭代一次,但是往往在开发中忽略了一些方法内部的实现,最后导致一个看似常识的问题却总以不同形式的bug出现。谨记!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值