Properties类按顺序输出加载内容
Properties类按顺序输出加载内容
最近手写工厂的时候,遇到了加载配置文件时不按照properties文件中的数据的顺序来加载。
一、问题代码
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesTest {
public static void main(String[] args) {
InputStream ips = null;
try {
ips = Properties.class.getResourceAsStream("/test.properities");
Properties props = new Properties();
props.load(ips);
for(String name:props.stringPropertyNames())
System.out.println(props.getProperty(name) + " "+name);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(ips != null){
ips.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
配置文件
cat=1
dog=2
bird=3
mouse=4
pig=5
输出结果

二、原因分析
public class Properties extends Hashtable<Object,Object>
上面是Properties类的定义,可以看到它继承了Hashtable类
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
load方法调用load0方法
private void load0 (LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
int limit;
int keyLen;
int valueStart;
char c;
boolean hasSep;
boolean precedingBackslash;
while ((limit = lr.readLine()) >= 0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
//System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
precedingBackslash = false;
while (keyLen < limit) {
c = lr.lineBuf[keyLen];
//need check if escaped.
if ((c == '=' || c == ':') && !precedingBackslash) {
valueStart = keyLen + 1;
hasSep = true;
break;
}
else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
valueStart = keyLen + 1;
break;
}
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
keyLen++;
}
while (valueStart < limit) {
c = lr.lineBuf[valueStart];
if (c != ' ' && c != '\t' && c != '\f') {
if (!hasSep && (c == '=' || c == ':')) {
hasSep = true;
} else {
break;
}
}
valueStart++;
}
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
}
load0方法可以看到最后取到key和value值后会调用父类Hashtable的put()方法,把数据存入Hashtable,具体的Hashtable源码这里就不再贴出。简单来说Hashtable的put()方法接收到值后会按照哈希值存储,而不是按照读取顺序存储。
接下来是读取时的源码,有兴趣的可以看一下:
public Set<String> stringPropertyNames() {
Hashtable<String, String> h = new Hashtable<>();
enumerateStringProperties(h);
return h.keySet();
}
enumerateStringProperties方法:
private synchronized void enumerateStringProperties(Hashtable<String, String> h) {
if (defaults != null) {
defaults.enumerateStringProperties(h);
}
for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
Object k = e.nextElement();
Object v = get(k);
if (k instanceof String && v instanceof String) {
h.put((String) k, (String) v);
}
}
}
Hashtable的keySet()方法
public Set<K> keySet() {
if (keySet == null)
keySet = Collections.synchronizedSet(new KeySet(), this);
return keySet;
}
三、解决方法
写一个工具类继承Properties类,实现以下功能:
- 创建一个能够按照读取顺序来存储properities文件中的key值的集合框架
- 能够返回步骤1创建的集合
在这里我采用了LinkedList来顺序存储key值(也可以采用别的集合类型),然后重写put方法,先把值存入自己建的LinkedList中,再调用父类的方法。关于返回Key值的集合是新写了一个orderStringPropertyNames()方法返回LinkedList
实现代码如下:
import java.util.LinkedList;
import java.util.Properties;
public class LinkedProperities extends Properties {
private LinkedList<String> linkedList = new LinkedList<String>();
@Override
public synchronized Object put(Object key, Object value) {
linkedList.add((String) key);
return super.put(key, value);
}
public LinkedList<String> orderStringPropertyNames() {
return linkedList;
}
}
四、结果测试

Properties类按顺序输出加载内容的更多相关文章
- Java 类中各成分加载顺序 和 内存中的存放位置
参加一个笔试,有一个关于类的静态代码块.构造代码块.构造函数的执行顺序的问题.不太清楚,网上百度了一下.在这里记录一下. 一.什么时候会加载类?使用到类中的内容时加载:有三种情况1.创建对象:new ...
- Java笔记(十二)……类中各部分加载顺序及存放位置问题
什么时候会加载类 使用到类中的内容时加载,三种情况: 创建对象:new StaticDemo(); 使用类中的静态成员:StaticCode.num = 9; StaticCode.getNum() ...
- struts2:struts.properties配置文件介绍及常量加载顺序
1. 背景 struts2框架中有两个核心配置文件,其中struts.xml文件主要负责管理应用中的action映射,以及该action包含的result定义等.除此之外,struts2框架还包括一个 ...
- java类的编译、加载和执行
一.java类的编译流程 这里主要讲的是从java文件到class文件 下图是java类编译的详细步骤: 1.词法分析:将java源代码的字符流转变为标记(Token)的集合,Token是编译过程中的 ...
- java类到底是如何加载并初始化的?
Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...
- (转)java类到底是如何加载并初始化的?
Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...
- Win8 Metro动态加载内容框架
制作背景 为了参加ImagineCup 2013 世界公民类比赛,我们设计制作了一个可动态扩展的幼教类App.这个App需要能动态加载内容,内容包括带动画可交互的电子书,动画,视频,游戏. 技术支持 ...
- js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面
js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 , 做手机端开发时,发现一个问题,有些浏览器,在网速比较慢的情况下,js文件没有加载完,后续的调用已经开始调用了, ...
- Java虚拟机——类的结构与加载
1.为什么Java可以跨平台 因为有java虚拟机,跨平台是因为字节码即class文件具有平台无关性,java代码会经过java虚拟机转换为字节码 2.class文件的结构 class文件主要是以8位 ...
随机推荐
- python爬虫(3)——用户和IP代理池、抓包分析、异步请求数据、腾讯视频评论爬虫
用户代理池 用户代理池就是将不同的用户代理组建成为一个池子,随后随机调用. 作用:每次访问代表使用的浏览器不一样 import urllib.request import re import rand ...
- C学习笔记(4)--- 指针的应用(第一部分)
1.指针(pointer)概念: 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明.指针变量声明的一般形式为: ...
- 8. 多态——编译时类型&运行时类型
一.引用变量的两种类型 1. 编译时类型:由声明该变量时使用的类型决定 2. 运行时类型:由实际赋给该变量的对象决定 如果编译时类型和运行时类型不一致,就可能出现多态. class BaseClass ...
- 迎国庆 itest(爱测试) 4.1.0 发布,开源BUG 跟踪管理 & 敏捷测试管理软件
v4.1.0 下载地址 :itest下载 itest 简介:查看简介 在线体验 https://itest.work/demo/ V4.1.0 根据用户反馈,共增加了23个更新:其中有11个功能增强和 ...
- Pwnable-mistake
先看看c的源码 #include <stdio.h> #include <fcntl.h> #define PW_LEN 10 #define XORKEY 1 void xo ...
- Vue 事件的基本使用与语法差异
"v-on:"可以简写为"@" "click"单击 "dblclick"双加 代码: <!doctype html ...
- 小白专场-树的同构-python语言实现
目录 一.题意理解 二.求解思路 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:<https://www.cnblogs.com/nickch ...
- mac pe简单安装方法
1.工具下载 TechTool Pro for mac V11.0.4:http://www.pc6.com/mac/112462.html 2.准备16g u盘 3.安装工具并按照注册码注册 在Te ...
- Leetcode算法题 7. Reverse Integer2
7. Reverse Integer 题目描述: Given a 32-bit signed integer, reverse digits of an integer. Example 1: Inp ...
- svg描边路径动画
svg描边路径动画<pre><!DOCTYPE html><html> <head> <meta charset="UTF-8" ...