Properties类按顺序输出加载内容

最近手写工厂的时候,遇到了加载配置文件时不按照properties文件中的数据的顺序来加载。

一、问题代码

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.util.Properties;
  4. public class PropertiesTest {
  5. public static void main(String[] args) {
  6. InputStream ips = null;
  7. try {
  8. ips = Properties.class.getResourceAsStream("/test.properities");
  9. Properties props = new Properties();
  10. props.load(ips);
  11. for(String name:props.stringPropertyNames())
  12. System.out.println(props.getProperty(name) + " "+name);
  13. } catch (IOException e) {
  14. e.printStackTrace();
  15. }finally {
  16. try {
  17. if(ips != null){
  18. ips.close();
  19. }
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25. }

配置文件

  1. cat=1
  2. dog=2
  3. bird=3
  4. mouse=4
  5. pig=5

输出结果

二、原因分析

  1. public class Properties extends Hashtable<Object,Object>

上面是Properties类的定义,可以看到它继承了Hashtable类

  1. public synchronized void load(InputStream inStream) throws IOException {
  2. load0(new LineReader(inStream));
  3. }

load方法调用load0方法

  1. private void load0 (LineReader lr) throws IOException {
  2. char[] convtBuf = new char[1024];
  3. int limit;
  4. int keyLen;
  5. int valueStart;
  6. char c;
  7. boolean hasSep;
  8. boolean precedingBackslash;
  9. while ((limit = lr.readLine()) >= 0) {
  10. c = 0;
  11. keyLen = 0;
  12. valueStart = limit;
  13. hasSep = false;
  14. //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
  15. precedingBackslash = false;
  16. while (keyLen < limit) {
  17. c = lr.lineBuf[keyLen];
  18. //need check if escaped.
  19. if ((c == '=' || c == ':') && !precedingBackslash) {
  20. valueStart = keyLen + 1;
  21. hasSep = true;
  22. break;
  23. }
  24. else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
  25. valueStart = keyLen + 1;
  26. break;
  27. }
  28. if (c == '\\') {
  29. precedingBackslash = !precedingBackslash;
  30. } else {
  31. precedingBackslash = false;
  32. }
  33. keyLen++;
  34. }
  35. while (valueStart < limit) {
  36. c = lr.lineBuf[valueStart];
  37. if (c != ' ' && c != '\t' && c != '\f') {
  38. if (!hasSep && (c == '=' || c == ':')) {
  39. hasSep = true;
  40. } else {
  41. break;
  42. }
  43. }
  44. valueStart++;
  45. }
  46. String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
  47. String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
  48. put(key, value);
  49. }
  50. }

load0方法可以看到最后取到key和value值后会调用父类Hashtable的put()方法,把数据存入Hashtable,具体的Hashtable源码这里就不再贴出。简单来说Hashtable的put()方法接收到值后会按照哈希值存储,而不是按照读取顺序存储。

接下来是读取时的源码,有兴趣的可以看一下:

  1. public Set<String> stringPropertyNames() {
  2. Hashtable<String, String> h = new Hashtable<>();
  3. enumerateStringProperties(h);
  4. return h.keySet();
  5. }

enumerateStringProperties方法:

  1. private synchronized void enumerateStringProperties(Hashtable<String, String> h) {
  2. if (defaults != null) {
  3. defaults.enumerateStringProperties(h);
  4. }
  5. for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
  6. Object k = e.nextElement();
  7. Object v = get(k);
  8. if (k instanceof String && v instanceof String) {
  9. h.put((String) k, (String) v);
  10. }
  11. }
  12. }

Hashtable的keySet()方法

  1. public Set<K> keySet() {
  2. if (keySet == null)
  3. keySet = Collections.synchronizedSet(new KeySet(), this);
  4. return keySet;
  5. }

三、解决方法

写一个工具类继承Properties类,实现以下功能:

  1. 创建一个能够按照读取顺序来存储properities文件中的key值的集合框架
  2. 能够返回步骤1创建的集合

在这里我采用了LinkedList来顺序存储key值(也可以采用别的集合类型),然后重写put方法,先把值存入自己建的LinkedList中,再调用父类的方法。关于返回Key值的集合是新写了一个orderStringPropertyNames()方法返回LinkedList

实现代码如下:

  1. import java.util.LinkedList;
  2. import java.util.Properties;
  3. public class LinkedProperities extends Properties {
  4. private LinkedList<String> linkedList = new LinkedList<String>();
  5. @Override
  6. public synchronized Object put(Object key, Object value) {
  7. linkedList.add((String) key);
  8. return super.put(key, value);
  9. }
  10. public LinkedList<String> orderStringPropertyNames() {
  11. return linkedList;
  12. }
  13. }

四、结果测试

Properties类按顺序输出加载内容的更多相关文章

  1. Java 类中各成分加载顺序 和 内存中的存放位置

    参加一个笔试,有一个关于类的静态代码块.构造代码块.构造函数的执行顺序的问题.不太清楚,网上百度了一下.在这里记录一下. 一.什么时候会加载类?使用到类中的内容时加载:有三种情况1.创建对象:new ...

  2. Java笔记(十二)……类中各部分加载顺序及存放位置问题

    什么时候会加载类 使用到类中的内容时加载,三种情况: 创建对象:new StaticDemo(); 使用类中的静态成员:StaticCode.num = 9;  StaticCode.getNum() ...

  3. struts2:struts.properties配置文件介绍及常量加载顺序

    1. 背景 struts2框架中有两个核心配置文件,其中struts.xml文件主要负责管理应用中的action映射,以及该action包含的result定义等.除此之外,struts2框架还包括一个 ...

  4. java类的编译、加载和执行

    一.java类的编译流程 这里主要讲的是从java文件到class文件 下图是java类编译的详细步骤: 1.词法分析:将java源代码的字符流转变为标记(Token)的集合,Token是编译过程中的 ...

  5. java类到底是如何加载并初始化的?

    Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...

  6. (转)java类到底是如何加载并初始化的?

    Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...

  7. Win8 Metro动态加载内容框架

    制作背景 为了参加ImagineCup 2013 世界公民类比赛,我们设计制作了一个可动态扩展的幼教类App.这个App需要能动态加载内容,内容包括带动画可交互的电子书,动画,视频,游戏. 技术支持 ...

  8. js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面

    js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 , 做手机端开发时,发现一个问题,有些浏览器,在网速比较慢的情况下,js文件没有加载完,后续的调用已经开始调用了, ...

  9. Java虚拟机——类的结构与加载

    1.为什么Java可以跨平台 因为有java虚拟机,跨平台是因为字节码即class文件具有平台无关性,java代码会经过java虚拟机转换为字节码 2.class文件的结构 class文件主要是以8位 ...

随机推荐

  1. [MySQL] mysql地理位置服务geometry字段类型

    这个字段类型是mysql5.7新增的功能,主要就是解决坐标存储和距离计算的常见问题 创建表:CREATE TABLE `service` ( `id` bigint(20) NOT NULL AUTO ...

  2. appium---adb logcat 命令详解

    我们在做app测试的过程中,肯定会遇到需要抓取日志问题,这几天安静也遇到了此问题,后台日志生成的太多了,保存本地了吧,设备多没有这么USB,通过wifi连接又太麻烦,你说这怎么是好?不要着急,我们往下 ...

  3. Java JDK 运行环境安装

    1 Windows系统 1.1 安装包准备 安装包本文档讲解为64位系统,如果是32位系统需要下载32位系统安装包 1.1.1 下载方式 打开jdk官方下载地址,该文档提供jdk版本为1.8 http ...

  4. Linux中自旋锁

    传统的spinlock Linux的的内核最常见的锁是自旋锁.自旋锁最多只能被一个可执行线程持有.如果一个执行线程试图获得一个被已经持有(争用)的自旋锁,那么该线程就会一直进行忙循环-旋转-等待锁重新 ...

  5. leetcode 贪心算法

    贪心算法中,是以自顶向下的方式使用最优子结构,贪心算法会先做选择,在当时看起来是最优的选择,然后再求解一个结果的子问题. 贪心算法是使所做的选择看起来都是当前最佳的,期望通过所做的局部最优选择来产生一 ...

  6. 全网最新方法:Win10下如何安装和搭建appium自动化测试环境

    为了方便大家,下面是本人安装和搭建appium所需要的软件,自取. 链接:https://pan.baidu.com/s/1wl5Xnos4BmnSZsBRd6B5YA#list/path=%2F  ...

  7. 正睿暑期培训day1考试

    链接 A 理解一下题意,然后玩几组样例就能发现,实际上就是\(k\)个\(i\)等价于\(1\)个\(i-1\).所以就类似于\(k\)进制进行进位,如果最后\(0\)位上不是\(0\),那么就存在划 ...

  8. A1010 Radix (25 分)

    一.技术总结 首先得写一个进制转换函数convert(),函数输入参数是字符串str和需要转化的进制(使用long long数据类型).函数内部知识,使用函数迭代器,即auto it = n.rbeg ...

  9. powersploit简介

    一.PowerSploit简介 PowerSploit是GitHub上面的一个安全项目,上面有很多powershell攻击脚本,它们主要被用来渗透中的信息侦察.权限提升.权限维持. Powershel ...

  10. 有关tab页的

    有关tab页的 1.静态的 2.动态的可以删除的 3.删除右侧,左侧,全部,除了自己以外的. 4.多了可以自动伸缩. 5.带shown事件.可以反向影响菜单去.