Map按value排序(由大到小-由小到大),对List列表分页

本文介绍如何在Java中实现Map的排序方法,包括按Key和Value排序,并详细展示了如何利用List进行分页处理,结合Map进行数据统计。
部署运行你感兴趣的模型镜像

 

一,Map排序

①Map按key排序

 

Map<String, Integer> sqrMap = Maps.newLinkedHashMap();
sqrMap = ...
List<String> allList = Lists.newLinkedList(sqrMap.keySet());
Collects.sort(allList);

 

②Map按value排序(由小到大)

 

 

Map<String, Integer> sqrMap = Maps.newLinkedHashMap();
ArrayList<Entry<String,Integer>> allList = Lists.newArrayList(sqrMap.entrySet());    
Collections.sort(allList, new Comparator<Map.Entry<String, Integer>>() {    
	 public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {    
	           Integer v1 = o1.getValue();
	           Integer v2 = o2.getValue();
	           return v1.compareTo(v2);  
	 } 
});  

 

 

③Map按value排序(由大到小)

 

Map<String, Integer> sqrMap = Maps.newLinkedHashMap();
ArrayList<Entry<String,Integer>> allList = Lists.newArrayList(sqrMap.entrySet());    
 Collections.sort(allList, new Comparator<Map.Entry<String, Integer>>() {    
	 public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {  
	            	Integer v1 = o1.getValue();
	            	Integer v2 = o2.getValue();
	            	Integer result = v2 - v1;
	            	if(result > 0){
	            		 return 1;
	            	}else if(result==0){
	            		return 0;
	            	}else{
	            		return -1;
	            	}
	   }
});  

 

 

二、在统计中,经常遇到非数据库数据的统计,这里我们使用List分页,结合Map来统计。

 

①、在ModelView controller里面获取分页列表。

 

ListPageModel<String> sqrListPage = getListPage(request,"pageNo", "pageSize");
view.addObject("sqrListPage",sqrListPage);

 

②、在页面代码

 

 

<table id="sqrTable" width="100%" cellpadding="0" cellspacing="0">
<tr class="title-1"><td>店铺名称</td></tr>
<c:forEach var="sqr" items="${sqrListPage.list }">
<tr><td>${sqr }</td></tr>
</c:forEach>
</table>
<div class="list-page">${sqrListPage}</div>

 

③、封装的getListPage方法

 

@SuppressWarnings({ "unchecked", "rawtypes" })
	private ListPageModel<String> getListPage(HttpServletRequest _request,String _pageNo,String _pageSize){
		int pageNo =  getIntParams(_request, _pageNo, 1);
		int pageSize = getIntParams(_request, _pageSize, Constant.MIN_DEFAULT_PAGE_SIZE);
		ListPageModel<String> listPage = null;
		Map<String, Integer> sqrMap = Maps.newLinkedHashMap();
		sqrMap.put("可人优品", 56);
		sqrMap.put("唯品衣秀", 12);
		sqrMap.put("温暖衣橱", 20);
		ArrayList<Entry<String,Integer>> allList = Lists.newArrayList(sqrMap.entrySet());    
        Collections.sort(allList, new Comparator<Map.Entry<String, Integer>>() {    
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {  
            	Integer v1 = o1.getValue();
            	Integer v2 = o2.getValue();
            	Integer result = v2 - v1;
            	if(result > 0){
            		 return 1;
            	}else if(result==0){
            		return 0;
            	}else{
            		return -1;
            	}
            }
        });  
		listPage = new ListPageModel(allList,pageSize);
        List<String> sqrList = listPage.getObjects(pageNo);
        listPage.setList(sqrList);
		return listPage;
	}

 

 ④分页工具类

public class ListPageModel<T> {
	private int currPageNo = 1; // 当前页
	private int totalPages = 0; // 总页数
	private int pageSize = Constant.MIN_DEFAULT_PAGE_SIZE;
	private int totalRows = 0; // 总数据数
	private int pageStartRow = 0;// 每页的起始数
	private int pageEndRow = 0; // 每页显示数据的终止数
	private boolean hasNextPage = false; // 是否有下一页
	private boolean hasPreviousPage = false; // 是否有前一页
	private List<T> list;

	public ListPageModel(List<T> list, int pageSize) {
		init(list, pageSize);// 通过对象集,记录总数划分
	}

	/**
	 * 初始化list,并告之该list每页的记录数
	 * 
	 * @param list
	 * @param pageSize
	 */
	public void init(List<T> list, int pageSize) {
		this.pageSize = pageSize;
		this.list = list;
		totalRows = list.size();
		hasPreviousPage = false;
		if ((totalRows % pageSize) == 0) {
			totalPages = totalRows / pageSize;
		} else {
			totalPages = totalRows / pageSize + 1;
		}

		if (currPageNo >= totalPages) {
			hasNextPage = false;
		} else {
			hasNextPage = true;
		}

		if (totalRows < pageSize) {
			this.pageStartRow = 0;
			this.pageEndRow = totalRows;
		} else {
			this.pageStartRow = 0;
			this.pageEndRow = pageSize;
		}
	}
	
	/**
	 * 获取第几页的内容
	 * 
	 * @param page
	 * @return
	 */
	public List<T> getObjects(int page) {
		if (page == 0){
			this.setCurrPageNo(1);
		}else{
			this.setCurrPageNo(page);
		}
		this.disposePage();
		if (page * pageSize < totalRows) {// 判断是否为最后一页
			pageEndRow = page * pageSize;
			pageStartRow = pageEndRow - pageSize;
		} else {
			pageEndRow = totalRows;
			pageStartRow = pageSize * (totalPages - 1);
		}

		List<T> objects = null;
		if (!list.isEmpty()) {
			objects = list.subList(pageStartRow, pageEndRow);
		}
		return objects;
	}
	
	/**
	 * 处理分页
	 */
	private void disposePage() {
		if (currPageNo == 0) {
			currPageNo = 1;
		}
		if ((currPageNo - 1) > 0) {
			hasPreviousPage = true;
		} else {
			hasPreviousPage = false;
		}

		if (currPageNo >= totalPages) {
			hasNextPage = false;
		} else {
			hasNextPage = true;
		}
	}

	/**
	 * 获取下一页
	 * @return
	 */
	public List<T> getNextPage() {
		currPageNo = currPageNo + 1;
		disposePage();
		return getObjects(currPageNo);
	}

	
	/**
	 * 获取上一页
	 * @return
	 */
	public List<T> getPreviousPage() {
		currPageNo = currPageNo - 1;
		if ((currPageNo - 1) > 0) {
			hasPreviousPage = true;
		} else {
			hasPreviousPage = false;
		}
		if (currPageNo >= totalPages) {
			hasNextPage = false;
		} else {
			hasNextPage = true;
		}
		return getObjects(currPageNo);
	}

//	public void description() {
//		String description = "共有数据数:" + this.getTotalRows() +
//		"共有页数: " + this.getTotalPages() +
//		"当前页数为:" + this.getPage() +
//		" 是否有前一页: " + this.isHasPreviousPage() +
//		" 是否有下一页:" + this.isHasNextPage() +
//		" 开始行数:" + this.getPageStartRow() +
//		" 终止行数:" + this.getPageEndRow();
//		System.out.println(description);
//	}

	/**
	 * 判断是否有下一页
	 * @return
	 */
	public boolean isNext() {
		return list.size() > 5;
	}
	
	/**
	 * 获取首页
	 * @return
	 */
	public List<T> getFistPage() {
		if (this.isNext()) {
			return list.subList(0, pageSize);
		} else {
			return list;
		}
	}

	public boolean isHasNextPage() {
		return hasNextPage;
	}
	
	public boolean isHasPreviousPage() {
		return hasPreviousPage;
	}

	//=====================================getter or setter===============================================
	public void setHasPreviousPage(boolean hasPreviousPage) {
		this.hasPreviousPage = hasPreviousPage;
	}
	
	public void setHasNextPage(boolean hasNextPage) {
		this.hasNextPage = hasNextPage;
	}

	public List<T> getList() {
		return list;
	}

	public void setList(List<T> list) {
		this.list = list;
	}

	public int getCurrPageNo() {
		return currPageNo;
	}

	public void setCurrPageNo(int currPageNo) {
		this.currPageNo = currPageNo;
	}

	public int getPageEndRow() {
		return pageEndRow;
	}

	public void setPageEndRow(int pageEndRow) {
		this.pageEndRow = pageEndRow;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getPageStartRow() {
		return pageStartRow;
	}

	public void setPageStartRow(int pageStartRow) {
		this.pageStartRow = pageStartRow;
	}

	public int getTotalPages() {
		return totalPages;
	}

	public void setTotalPages(int totalPages) {
		this.totalPages = totalPages;
	}

	public int getTotalRows() {
		return totalRows;
	}

	public void setTotalRows(int totalRows) {
		this.totalRows = totalRows;
	}
	
	//================================分页=================================
	private String funcName = "listpage"; 
	public String getFuncName() {
		return funcName;
	}
	public void setFuncName(String funcName) {
		this.funcName = funcName;
	}
	/**
	 * 默认输出当前分页标签 <div class="page">${page}</div>
	 */
	@Override
	public String toString() {
		String div1="<div class=\"total-pages fl\">" + currPageNo  + "/" + totalPages + "</div>\n";
		StringBuilder div2=new StringBuilder();
		div2.append("<div class=\"pagination\">\n<ul>\n");
		if (currPageNo==1) {// 如果是首页
			div2.append("<li class=\"pglink pre\"><a href=\"javascript:\" title=\"上一页\" class=\"disabled\"><span><i></i></span></a></li>\n");
		} else {
			div2.append("<li class=\"pglink pre\"><a href=\"javascript:" + getFuncName() + "(" + (currPageNo - 1) + ","+ pageSize + ");\" title=\"上一页\"><span><i></i></span></a></li>\n");
		}
		if (currPageNo == totalPages) {
			div2.append("<li class=\"pglink next\"><a href=\"javascript:\" title=\"下一页\" class=\"disabled\"><span><i></i></span></a></li>\n");
		} else {
			div2.append("<li class=\"pglink next\"><a href=\"javascript:" + getFuncName() + "(" + (currPageNo + 1) + "," + pageSize + ");\" title=\"下一页\">" + "<span><i></i></span></a></li>\n");
		}
		div2.append("<li class=\"skippage\">第<input type=\"text\" id=\"rePageNo\" value=\""+currPageNo+"\" class=\"input-mini\"/>页</li>\n");
		div2.append("<li class=\"\"><a title=\"跳转\" onclick=\"javascript:" + getFuncName() + "($(this).parent().parent().find('#rePageNo').val()," + pageSize + ");\" target=\"_self\"/><span>GO</span></a></li>\n");
		div2.append("</ul>\n</div>\n");
		
		StringBuilder sb = new StringBuilder();
		sb.append(div1).append(div2);
		sb.insert(0,"<div class=\"pager original-state\">\n").append("</div>\n");
		return sb.toString();
	}
}

 

 

欢迎来我的小店看看》》》《可人优品》》》

原文地址:http://vipshow.iteye.com/blog/2038026

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think>好的,我现在需要帮助用户修改现有的Java代码,使得统计数据能按从到小排序,并且限制返回最多的10条记录。首先,我需要回顾用户之前的代码和之前的回答,确保这次修改符合他们的需求。 用户提供的代码是一个Java方法,使用Stream API对书籍列表进行处理,按书名分组并计算每本书的总点击量。之前的修改是在分组后使用limit(5)来限制结果数量为5条,现在用户希望改为降序排序并取前10条。 首先,我需要确定在哪里加入排序逻辑。根据之前的代码,分组后的Map被转换为流,然后进行限制。但用户现在需要的是先按统计值(即count的总和)降序排序,然后取前10条。因此,应该在调用limit(10)之前,添加一个sorted操作。 接下来,如何实现降序排序呢?在Java流中,可以使用Comparator来定义排序规则。对于Map.Entry对象,可以通过比较它们的值(即每个书名的总count)来排序。降序排序需要将比较器反转,或者使用Comparator.comparingInt并传递一个负号,但更常见的做法是使用Map.Entry.comparingByValue(Comparator.reverseOrder())。 然后,需要考虑分组后的Map是否是有序的。默认情况下,Collectors.groupingBy返回的是HashMap,不保证顺序。因此,在排序前,需要将entrySet转为流,然后进行排序,确保处理后的结果是有序的。或者,在分组时使用LinkedHashMap来保持插入顺序,但这可能不必要,因为后续的排序会覆盖原有的顺序。 另外,用户之前的问题中引用到,当数据量超过一万时,索引排序可能不如FileSort高效,因此建议使用limit和where过滤减少数据量。这可能意味着在处理数据时,先过滤和限制数据量能提升性能。但在这个代码中,数据已经在内存中处理,所以主要考虑的是如何高效地对分组后的结果进行排序和限制。 还需要注意,用户希望将结果限制为前10条,因此需要将原来的limit(5)改为limit(10)。同时,确保在排序之后应用limit,这样才能得到正确的前10条最数据。 现在,整合这些步骤到代码中: 1. 在分组后,将entrySet转为流。 2. 使用sorted方法,按值的降序排序。 3. 限制结果为前10条。 4. 收集回Map中。 此外,原来的代码在分组后的收集是直接转为Map,但为了保持排序后的顺序,可能需要使用LinkedHashMap,否则后续遍历时可能无法保持顺序。因此,在收集的时候,应该指定使用LinkedHashMap来保持插入顺序,这样后续遍历时xAsis和yAsis列表中的顺序才会正确。 最后,测试修改后的代码,确保排序和限制都正确应用,并且结果符合预期。</think>### 修改后的代码实现 基于您的要求和引用[1][2]中关于数据量排序优化的建议,结合现有代码结构,以下是按 `count` 降序排序并限制前 10 条的修改方案: ```java public Result click() { List<Book> list = bookService.list(); // 新增排序逻辑:按 count 降序,取前10条 Map<String, Integer> collect = list.stream() .filter(x -> ObjectUtils.isNotEmpty(x.getName())) .collect(Collectors.groupingBy( Book::getName, Collectors.summingInt(Book::getCount) )) .entrySet().stream() .sorted(Map.Entry.<String, Integer>comparingByValue().reversed()) // 按值降序 .limit(10) // 限制前10条 .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> oldVal, // 合并函数 LinkedHashMap::new // 保持排序后的顺序 )); List<String> xAsis = new ArrayList<>(); List<Long> yAsis = new ArrayList<>(); for (Map.Entry<String, Integer> entry : collect.entrySet()) { xAsis.add(entry.getKey()); yAsis.add(entry.getValue().longValue()); } Map<String, Object> map = new HashMap<>(); map.put("xAsis", xAsis); map.put("yAsis", yAsis); return Result.success(map); } ``` --- ### 关键修改说明 1. **降序排序实现** - 通过 `.sorted(Map.Entry.comparingByValue().reversed())` 实现按 `count` 值的降序排列 - `comparingByValue()` 默认升序,`.reversed()` 反转顺序[^1] 2. **有序结果保留** - 使用 `LinkedHashMap::new` 作为最终收集器,确保遍历时按排序后的顺序输出 - 普通 `HashMap` 会丢失排序结果(引用[1]提到的索引失效问题类似) 3. **性能优化** - 先过滤空书名(`ObjectUtils.isNotEmpty(x.getName())`),减少无效数据参与排序 - 通过 `limit(10)` 限制内存中处理的数据量(符合引用[1]的优化建议) --- ### 相关知识点 1. **流处理中的有状态操作** `sorted()` 是有状态操作,会将所有数据加载到内存排序数据量时需谨慎(参考引用[3]的数据清洗原则) 2. **`LinkedHashMap` 的作用** 保持键值对的插入顺序,与 `HashMap` 的无序特性形成对比,适用于需要保留排序结果的场景 3. **合并函数的意义** `(oldVal, newVal) -> oldVal` 用于处理键冲突,此处因分组后键唯一可简写,但需保持语法完整性 --- ### 相关问题 1. **如何实现多级排序(先按 count 降序,再按书名升序)?** - 修改比较器: ```java .sorted(Comparator.comparing((Map.Entry<String, Integer> e) -> e.getValue()).reversed() .thenComparing(Map.Entry::getKey)) ``` 2. **如果数据量超过百万级,如何优化性能?** - 在数据库层添加 `WHERE` 条件过滤(如最近7天数据),减少内存处理量(引用[2]的日志分析策略) - 使用并行流 `.parallelStream()` 加速处理(需确保线程安全) 3. **如何避免 `sorted()` 导致的内存溢出?** - 结合引用[1]的建议,在数据库查询阶段通过 `LIMIT` 预过滤(如 `SELECT ... ORDER BY count DESC LIMIT 10`) - 使用分页分批处理(适用于无法一次性加载全量数据的场景) [^1]: 流式排序需要加载全量数据到内存 [^2]: 通过预过滤减少内存处理量 [^3]: 有序数据结构对结果展示至关重要
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值