java遍历元素中的每个子元素,树形展示

情景:

有个项目需要和其他公司对接接口,他们并不是直接使用httpClient模拟http协议的方式交互数据,而是使用它们提供的jar包,当然没有功夫去看他们提供的jar包里面是通过什么方式交互数据,不过提供的方法使用也挺方便,但是方法返回的是一个对象,困难的是这个对象结构有点复杂,也没有结构文档,和他们沟通也是有一句没一句的回复。没有办法只能自己慢慢看,但是效率太低。这时候想如何能将一个java对象的每个元素打印处理来看着也方便,通过一天的琢磨和改进,实现一版类似windows的dos命令中tree命令的展示方式的工具类。

展示:

1.遍历对象

2.遍历文件夹

工具类:DataFormat

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class DataFormat {
	
	private PrintPattern pattern;
	
	public DataFormat(){
		initDefPattern();
	}
	
	public DataFormat(PrintPattern pattern){
		if(null != pattern){
			this.pattern = pattern;
		}else{
			initDefPattern();
		}
	}
	
	private void initDefPattern(){
		this.pattern = new PrintPattern() {
			public void printTarget(String str) {
				System.out.print(str);
			}
			
			public void newLine() {
				System.out.println("");
			}

			public void end() {
				
			}
		};
	}
	
	public static interface TreeNode{
		public boolean isMap();
		public boolean isCollection();
		public boolean isBasic();
		
		public Map<String,TreeNode> getMap();
		public Collection<TreeNode> getCollection();
		public Object getBasic();
		public TreeNode toMapNode();
	}
	
	public static interface PrintPattern{
		public void newLine();
		public void printTarget(String str);
		public void end();
	}
	
	public static class FileTreeNode implements TreeNode{

		File file = null;
		
		public FileTreeNode(File file) {
			this.file = file;
		}
		
		public boolean isMap() {
			return  this.file.isDirectory();
		}

		public boolean isCollection() {
			return false;
		}

		public boolean isBasic() {
			return this.file.isFile();
		}

		public Map<String, TreeNode> getMap() {
			Map<String,TreeNode> mapContainer = new TreeMap<String, TreeNode>();
			File[] listFiles = this.file.listFiles();
			for (int i = 0; i < listFiles.length; i++) {
				mapContainer.put(listFiles[i].getName(),new FileTreeNode(listFiles[i]));
			}
			return mapContainer;
		}

		public Collection<TreeNode> getCollection() {
			return null;
		}

		public Object getBasic() {
			return this.file.getName();
		}

		public TreeNode toMapNode() {
			return null ;
		}
		
	}
	
	static class ObjectTreeNode implements TreeNode{

		private Object obj;
		
		public ObjectTreeNode(Object obj){
			this.obj = obj;
		}
		
		//将自定义的对象作为一个map
		public boolean isMap() {
			
			boolean isMap = isRealMap() || (!isBasic() && ! isCollection()) ;
			
			return isMap;
		}
		
		private boolean isRealMap(){
			Class<? extends Object> type = this.obj.getClass();
			return Map.class.isAssignableFrom(type);
		}

		public boolean isCollection() {
			return Collection.class.isAssignableFrom(this.obj.getClass());
		}

		public boolean isBasic() {
			Class<? extends Object> type = this.obj.getClass();
			
			boolean isBasic = type.isPrimitive() 
			|| Integer.class.equals(type)
			|| String.class.equals(type)
			|| Byte.class.equals(type)
			|| Character.class.equals(type)
			|| Short.class.equals(type)
			|| Long.class.equals(type)
			|| Float.class.equals(type)
			|| Double.class.equals(type)
			|| Boolean.class.equals(type);
			
			return isBasic;
		}


		public Map<String, TreeNode> getMap() {
			if(isRealMap()){
				Map<String, Object> mapValues = (Map<String,Object>)this.obj;
				Set<Entry<String, Object>> nodeSet = mapValues.entrySet();
				
				Map<String,TreeNode> mapContainer = new TreeMap<String, TreeNode>();
				for (Entry<String, Object> entry : nodeSet) {
					mapContainer.put(entry.getKey(), new ObjectTreeNode(entry.getValue()));
				}
				
				return mapContainer;
			}else{ //自定义对象对象
				Class<? extends Object> type = this.obj.getClass();
				
				Map<String,TreeNode> mapContainer = new TreeMap<String, TreeNode>();
				
				Field[] declaredFields = type.getDeclaredFields();
				for (Field field : declaredFields) {
					try {
						field.setAccessible(true);
						mapContainer.put(field.getName(), new ObjectTreeNode(field.get(this.obj)));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				return mapContainer;
			}
		}

		public Collection<TreeNode> getCollection() {
			Collection<Object> listValues = (Collection<Object>)this.obj;
			ArrayList<TreeNode> treeNods = new ArrayList<TreeNode>();
			
			Map<String,Object> map = null;
			for (Object object : listValues) {
				treeNods.add(new ObjectTreeNode(object));
			}
			
			return treeNods;
		}

		public Object getBasic() {
			return this.obj;
		}

		public TreeNode toMapNode() {
			Map<String,Object> mapContainer = new TreeMap<String, Object>();
			mapContainer.put(this.obj.getClass().getName(), this.obj);
			return new ObjectTreeNode(mapContainer) ;
		}
		
		
	}
	
	private void printKey(Object key,boolean[] last){
		for(int i=0,length = last.length -1 ; i < length ; i++	){
			if(last[i]){
				printTarget("   ");
			}else{
				printTarget("│  ");
			}
		}
		
		if(last[last.length-1]){
			printTarget("└─");
		}else{
			printTarget("├─");
		}
		
		printTarget(key.toString());
	}
	
	private void printValue(Object value,boolean[] last){
		printTarget("=["+value+"]");
	}
	
	public void newLine(){
		this.pattern.newLine();
	}
	
	public void printTarget(String str){
		this.pattern.printTarget(str);
	}
	
	public void tree(TreeNode node){
		tree(node,new boolean[]{true});
		this.pattern.end();
	}
	
	
	//map的value可以是 map,list,基本类型
	//list的value只能是map,基本类型
	private void tree(TreeNode node,boolean[] last){
		
		if(node.isCollection()){
			Collection<TreeNode> collection = node.getCollection();
			
			int index = 1;
			for (TreeNode value : collection) {
				if(collection.size() == index){
					last[last.length - 1] = true;
				}else{
					last[last.length - 1] = false;
				}
				index ++ ;
				
				if(value.isBasic()){
					printKey("["+value.getBasic()+"]",last);
					newLine();
				}else if(value.isMap()){
					value = value.toMapNode();
					Set<Entry<String, TreeNode>> entrySet = value.getMap().entrySet();
					for (Entry<String, TreeNode> entry : entrySet) {
						printKey(entry.getKey(), last);
						newLine();
						boolean[] nextLast = getNextLast(last);
						notCollection(entry.getValue(),nextLast);
					}
				}
			}
		}else{
			notCollection(node,last);
		}
	}
	
	//map
	private void notCollection(TreeNode node,boolean[] last){
		if(node.isMap()){
			Set<Entry<String, TreeNode>> nodeSet = node.getMap().entrySet();
			int index = 1;
			for (Entry<String, TreeNode> entry : nodeSet) {
				if(nodeSet.size() == index){
					last[last.length - 1] = true;
				}else{
					last[last.length - 1] = false;
				}
				index ++ ;
				
				printKey(entry.getKey(),last);
				
				if(entry.getValue().isBasic()){
					printValue(entry.getValue().getBasic(),last);
					newLine();
				}else{
					boolean[] nextLast = getNextLast(last);
					newLine();
					tree(entry.getValue(),nextLast);
				}
			}
		}else{
			printKey(node,last);
			newLine();
		}
	}
	
	private boolean isBasicType(Class<?> type){
		return !Map.class.isAssignableFrom(type) && !Collection.class.isAssignableFrom(type);
	}
	
	private boolean[] getNextLast(boolean[] last){
		boolean[] nextLast = new boolean[last.length+1];
		System.arraycopy(last, 0, nextLast, 0, last.length);
		return nextLast;
	}
}

使用示例:

1.遍历文件夹打印在控制台,并输出到文件中

public class TreeTest {
	@Test
	public void test1(){
		try {
			DataFormat df = new DataFormat(new DataFormat.PrintPattern() {
				StringBuffer sb = new StringBuffer(500);
				
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\nginx.txt",true));
				
				
				
				public void printTarget(String str) {
					System.out.print(str);
					sb.append(str);
				}
				
				public void newLine() {
					System.out.println("");
					sb.append("\r\n");
					try {
						bos.write(sb.toString().getBytes("UTF-8"));
						sb.setLength(0);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				public void end() {
					try {
						bos.flush();
						bos.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			});
			
			df.tree(new DataFormat.FileTreeNode(new File("D:\\source\\nginx")));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2.遍历元素打印在控制台

	public static void main(String[] args) {
		DataFormat df = new DataFormat();
		
		ClassRoom ynj = new ClassRoom();
		ynj.setGrade("向日葵奋进班");
		
		ArrayList<Student> students = new ArrayList<Student>();
		
		Student xm = new Student();
		xm.setId(1);
		xm.setName("小明");
		xm.setAge(8);
		
		students.add(xm);
		
		Student xh = new Student();
		xh.setId(2);
		xh.setName("小花");
		xh.setAge(7);
		
		students.add(xh);
		
		
		Student xg = new Student();
		xg.setId(3);
		xg.setName("小刚");
		xg.setAge(10);
		
		students.add(xg);
		
		ynj.setStudents(students);
		
		df.tree(new ObjectTreeNode(ynj), new boolean[]{true});
		
	}

其他说明:

问题:

1.没有过滤功能,可以扩展

2.ObjectTreeNode中基本上没有判断null值,也就说如果元素中有null值则会报错,需要修改

扩展:

1.TreeNode接口:定义树中节点的类型,DataFormat内提供两个TreeNode实现类FileTreeNode用于遍历文件夹、ObjectTreeNode用于遍历java对象。如果需要遍历其它则需要实现TreeNode接口 map:key value的列表  collection:一个key对应多个value  basic:最小的不可再拆分的

2.PrintPattern接口:定义输出的类型。DataFormat内提供一个默认的控制台输出方式,如果需要自定义则实现该接口,在实例化DataFormat对象时通过构造函数传入

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值