论坛首页 Java企业应用论坛

发个行转列的代码,顺便了解下大家是如何进行行转列

浏览 6364 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (2)
作者 正文
   发表时间:2009-07-21   最后修改:2009-07-21
package com.saturday;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 一个行转列的小程序,将如下结构的数据:
 *    c1,c2,pk,fk1,v1
 *    c1,c2,pk,fk2,v2
 *    c1,c2,pk,fk3,v3
 *    .....
 *  转化为:
 *    c1,c2,pk,v1,v2,v3.....
 *    
 * @author 王建波
 *
 */
public class Record2Horrizen {
	public static void main(String[] args){
		List<Map> records=getRecords(
						DataGetter.getData(),
						"id",
						"course",
						"grade"
					);
		String sTemplete=" ID:%1$-10s"
		                +"姓名:%2$-10s"
        				+"语文:%3$-10s"
        				+"数学:%4$-10s"	
        				+"英语:%5$-10s"	
        				+"物理:%6$-10s";
        				
		for(Map record:records){
			System.out.println(String.format(
				sTemplete,
				record.get("id"),
				record.get("name"),
				record.get("语文")!=null?record.get("语文"):"--",
				record.get("数学")!=null?record.get("数学"):"--",
				record.get("英语")!=null?record.get("英语"):"--",
				record.get("物理")!=null	?record.get("物理"):"--"			
			));
		}
	}
	
	
	/**
	 * 获取行专列后的列表
	 * @param list 原始数据列表(需要提前按主键排序)
	 * @param sPKF 主键字段名称
	 * @param sFKF 外键字段名称
	 * @param sFVF 值字段名称
	 * @return
	 */
	public static List<Map> getRecords(List<Map> list,
									   String sPKF,
									   String sFKF,
									   String sVF){
		List<Map> results=new ArrayList<Map>();		
		
		if(list instanceof List&&list.size()>0){
			Map record,preRecord,rowDataCatch=new HashMap();
			Set<String> colSet=getColSet(list,sFKF,sVF);
			Object pk=list.get(0).get(sPKF);
			
			for(int i=0,len=list.size();i<len;i++){
				record=list.get(i);
				
				//当主键发生跳变或最后一条记录时,行转列输出
				if(i==len-1||!record.get(sPKF).equals(pk)){					
					/*
					 * 若最后一行触发的输出,提前写入缓存。因为写缓存
					 * 操作发生在判断之后,若不这样最后一条数据会被漏掉
					*/
					if(i==len-1){
						rowDataCatch.put(
							record.get(sFKF),
							record.get(sVF)
						);						
					}					
					preRecord=list.get(i-1);
					preRecord.remove(sFKF);
					preRecord.remove(sVF);					
					preRecord.putAll(rowDataCatch);
					
					addRecord(results,colSet,preRecord);
					
					//重新设置主键标记和行数据缓存
					rowDataCatch.clear();
					pk=record.get(sPKF);
				}
				
				//将外键值值字段写入行数据缓存
				if(i<len-1){
					rowDataCatch.put(
						record.get(sFKF),
						record.get(sVF)
					);
				}	
			}
		}
		
		return results;
	}
	
	/**
	 * 统计所有输出列
	 * @param list 数据列表
	 * @param sFKF 外键字段名称
	 * @param sVF  值字段名称
	 * @return
	 */
	private static Set<String> getColSet(List<Map> list,
									    String sFKF,
									    String sVF){
		
		Set<String> colSet=new HashSet<String>();
		
		if(list instanceof List&&list.size()>0){
			Map record=list.get(0);
			
			//非变化字段集合
			for(Object key:record.keySet()){
				if(!key.equals(sFKF)&&!key.equals(sVF))
					colSet.add(key.toString());
			}
			
			//变化字段集合
			for(Map item:list){
				colSet.add((String)item.get(sFKF));
			}
		}		
		
		return colSet;
	}
	
	/**
	 * 将行数据进行列补齐操作后写入输出列表
	 * @param list
	 * @param colSet
	 * @param rowData
	 */
	private static void addRecord(List<Map> list,
			                     Set<String> colSet,
			                     Map rowData){		
		//补齐不存在的列
		for(String column:colSet){
			if(!rowData.containsKey(column)){
				rowData.put(column,null);
			}			
		}
		
		list.add(rowData);
	}
}


从数据库读数据比较麻烦,手动添了几条数据
package com.saturday;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DataGetter {
	public static List<Map> getData(){
		List<Map> datas=new ArrayList<Map>();
		Map record;
		
		//记录1
		record=new HashMap();
		record.put("id", "id-1");
		record.put("name","姓名1");
		record.put("course","语文");
		record.put("grade", 30);
		datas.add(record);
		
		record=new HashMap();
		record.put("id", "id-1");
		record.put("name","姓名1");
		record.put("course","数学");
		record.put("grade", 40);
		datas.add(record);	
		
		record=new HashMap();
		record.put("id", "id-1");
		record.put("name","姓名1");
		record.put("course","英语");
		record.put("grade",60);
		datas.add(record);			

		//记录2
		record=new HashMap();
		record.put("id", "id-2");
		record.put("name","姓名2");
		record.put("course","语文");
		record.put("grade", 60);
		datas.add(record);
		
		record=new HashMap();
		record.put("id", "id-2");
		record.put("name","姓名2");
		record.put("course","物理");
		record.put("grade", 80);
		datas.add(record);	
		
		//记录3
		record=new HashMap();
		record.put("id", "id-3");
		record.put("name","姓名3");
		record.put("course","语文");
		record.put("grade", 60);
		datas.add(record);
		
		record=new HashMap();
		record.put("id", "id-3");
		record.put("name","姓名3");
		record.put("course","英语");
		record.put("grade", 80);
		datas.add(record);
		
		return datas;
	}
}


控制台输出:
ID:id-1      姓名:姓名1       语文:30        数学:40        英语:60        物理:--       
ID:id-2      姓名:姓名2       语文:60        数学:--        英语:--        物理:80       
ID:id-3      姓名:姓名3       语文:60        数学:--        英语:80        物理:--            
   发表时间:2009-07-21  
我行列转换一般在数据库测用sql实现。
0 请登录后投票
   发表时间:2009-07-21  
以前我们也用数据库实现,但很麻烦尤其是换数据库的时候,还要重写
0 请登录后投票
   发表时间:2009-07-22  
map(key,value)

key = x作标_y作标
0 请登录后投票
   发表时间:2009-07-22  
如果把map换成对象之后,又怎么实现呢.
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics