编写一个程序,对于给定的一组数据和要求,输出一个以字符组成的柱状图。
输入
第一行,一个整数 N(1<=n<=20),表示这组数据的条目数。
第二行,两个字符串,用于表示数据展示在柱状图上的排序方式。第一个字符串是“Name” 或者 “Value”,表示排序的依据是数据条目的名称亦或数值;第二个字符串是 “ASC” 或者 “DESC”,表示升序或降序。
随后的 N 行,每行包含一个字符串 S 和一个数字 V,以空格分隔,表示一条数据。S 即数据条目的名称,仅包含小写字母,V 即对应的数值,是一个整数,(0<=V<=1,000,000)
输出
图表中名称区域的宽度,由这组数据中名称的最大长度决定,所有名称向右对齐, 图表中柱的最大长度为 20,每个柱的长度由该柱对应数据和这组数据中最大值(此值一定大于 0)的比值与 20 相乘获得,不足一格的部分舍去。
输入示例
3
Value DESC
apple 5
pen 3
pineapple 10
输出示例
┌─────────┬────────────────────┐ │pineapple│████████████████████│ ├─────────┼────────────────────┤ │ apple│██████████ │ ├─────────┼────────────────────┤ │ pen│██████ | └─────────┴────────────────────┘
(等宽字体下,输出应当形如下图)

图表外框转角符号:
- “┌”(\u250c)
- “┐”(\u2510)
- “└”(\u2514)
- “┘”(\u2518)
图表中的横、竖线:
- “─”(\u2500)
- “│”(\u2502)
图表中的各种交叉线:
- “├”(\u251c)
- “┤”(\u2524)
- “┬”(\u252c)
- “┴”(\u2534)
- “┼”(\u253c)
用来拼柱子的字符:
- “█”(\u2588)
图表中的空格:
- “ ”(\u0020)
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
/**
* 第一行,一个整数 N(1<=n<=20),表示这组数据的条目数。
第二行,两个字符串,用于表示数据展示在柱状图上的排序方式。第一个字符串是“Name” 或者 “Value”,
表示排序的依据是数据条目的名称亦或数值;第二个字符串是 “ASC” 或者 “DESC”,表示升序或降序。
随后的 N 行,每行包含一个字符串 S 和一个数字 V,以空格分隔,表示一条数据。S 即数据条目的名称,
仅包含小写字母,V 即对应的数值,是一个整数,(0<=V<=1,000,000)
例如:3
Value DESC
apple 5
pen 3
pineapple 10
* @author CGX~LL
*
*/
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
in.useDelimiter(";");//将;设置为分隔符
String string = in.next();
//此时可进行输入!
SeePicture(string);
in.close();
}
private static void SeePicture(String string) {
//1.首先将这个大字符串分隔开(用\r分割)
//2.将分割后的子字符串分别处理
String[] temp = string.split("\r\n");
int num = Integer.parseInt(temp[0]);//表示行数
String sortStyle = temp[1].split(" ")[0];//表示排序方式
String upOrDown = temp[1].split(" ")[1];//表示升序或是降序
//后面的数据需要存在HashMap中进行排序
Map<String, Integer> map = new LinkedHashMap<>();
//从第三行数据开始插入,一直到第num行
for(int i = 2;i<num+2;i++) {
map.put(temp[i].split(" ")[0], Integer.parseInt(temp[i].split(" ")[1]));
}
//参数校验
if(num<1 || num>20) {//按要求,行数越界了
System.out.println("行数不在范围内,1<=num<=20");
return;
}
if("Name".equals(sortStyle) == false && "Value".equals(sortStyle) == false) {//按要求,排列方式输错了
System.out.println("请输入正确的排序方式,Name or Value");
return;
}
if("ASC".equals(upOrDown) == false && "DESC".equals(upOrDown) == false) {//按要求,升序或者降序输错了
System.out.println("请输入正确的升降序方式,ASC or DESC");
return;
}
map = sortHashMap(map, sortStyle, upOrDown);
//至此,该集合已经全部存入map(并按照指定顺序)
//接下来进行输出
drawResult(map,num);
}
public static Map<String,Integer> sortHashMap(Map<String,Integer> map,String sortStyle,String upOrDown)//HashMap排序
{
List<Map.Entry<String,Integer>> list = new LinkedList<Map.Entry<String,Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String,Integer>>()
{
@Override
public int compare(Map.Entry<String,Integer> o1, Map.Entry<String,Integer> o2)
{
if("Value".equals(sortStyle)) {//按value进行排序
if("ASC".equals(upOrDown)) {//升序
int compare = o1.getValue()-o2.getValue();
return compare;
}else {//降序
int compare = o1.getValue()-o2.getValue();
return -compare;
}
}else {
if("ASC".equals(upOrDown)) {//按Name进行排序,升序
int compare = (o1.getKey()).compareTo(o2.getKey());
return compare;
}else {//降序
int compare = (o1.getKey()).compareTo(o2.getKey());
return -compare;
}
}
}
});
Map<String,Integer> result = new LinkedHashMap<>();
for (Map.Entry<String,Integer> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
private static void drawResult(Map<String, Integer> map,int num) {//结果图
//分别得到map中key、value的最大长度
Set<String> set = map.keySet();
int keyMaxSize = maxSize(set);
Collection<Integer> set2 = map.values();
int valueMaxSize = maxNum(set2);
//将map中的key存入数组中,方便通过下标访问,再通过key得到value
String[] array = getKeys(map,num);
for(int i=1,m=0;i<2*num+2;i++) {
if(i == 1) {//第一行
System.out.print("\u250c");
int j = keyMaxSize;
while(j>0) {
System.out.print("\u2500");
j--;
}
System.out.print("\u252c");
int k = valueMaxSize;
while(k>0) {
System.out.print("\u2500");
k--;
}
System.out.println("\u2510");
}
else if(i%2 == 0) {//有数据的行
System.out.print("\u2502");
int j = keyMaxSize-array[m].length();
while(j>0) {
System.out.print(" ");
j--;
}
System.out.print(array[m]);
System.out.print("\u2502");
int k = map.get(array[m]);
int k2 = valueMaxSize-k;
while(k>0) {
System.out.print("\u2588");
k--;
}
while(k2>0) {
System.out.print(" ");
k2--;
}
System.out.println("\u2502");
m++;
}
else if(i == 2*num+1) {//最后一行
System.out.print("\u2514");
int j = keyMaxSize;
while(j>0) {
System.out.print("\u2500");
j--;
}
System.out.print("\u2534");
int k = valueMaxSize;
while(k>0) {
System.out.print("\u2500");
k--;
}
System.out.println("\u2518");
}
else {//其他行(无数据,也不是在首行或者末行)
System.out.print("\u251c");
int j = keyMaxSize;
while(j>0) {
System.out.print("\u2500");
j--;
}
System.out.print("\u253c");
int k = valueMaxSize;
while(k>0) {
System.out.print("\u2500");
k--;
}
System.out.println("\u2524");
}
}
}
private static int maxNum(Collection<Integer> set2) {//取得set集合中最大的值(Integer)
Iterator<Integer> iterator = set2.iterator();
int len = 0;
while(iterator.hasNext()) {
int temp = iterator.next();
if(temp > len) {
len = temp;
}
}
return len;
}
private static int maxSize(Set<String> set2) {//取出set集合中长度最长数据的长度(String)
Iterator<String> iterator = set2.iterator();
int len = 0;
while(iterator.hasNext()) {
String string = iterator.next();
int temp = string.length();
if(temp > len) {
len = temp;
}
}
return len;
}
private static String[] getKeys(Map<String, Integer> map,int num) {//取得map集合中key,并将其存入数组中
String[] array = new String[num];
int i=0;
Set<String> set = map.keySet();
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
array[i++] = iterator.next();
}
return array;
}
}尝试输入几个例子看看结果:(运行环境——Eclipse)


假如故意输入错误的参数:
很明显,会得到提醒;
版权声明:本文为ChenGX1996原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。