Springboot+Vue、HashMap实现词频统计功能

要求:统计数据库某一列中字段的重复次数,即词频,并在前端以a-tag标签的形式展示词频最高的前n项。

一、后端部分

假设数据库中存在一列keywords,如下:

idkeywords
1aa,b,cc
2aa,cc
3b
4

aa,d

每一行代表一条数据,数据的keywords中,不同的keywords用符号(我这里就用的中文逗号)做分割,我要得到aa,b,cc,d这几个元素出现的次数,并按词频从高到低排序,即得到下图:

aa3
b2
cc2
d1

lets do it~

分析:利用HashMap解决,其中aa,b,cc,d作为map中的key,其对应出现的次数作为map中的value,按照value值从高到低输出。

idea中springboot文件目录如下,我个人理解的顺序是这样:数据库数据-->entity层-->service层下impl的类-->service层的接口-->controller层与前端交互。

 

1.entity层,定义一个实体类FaultHanding存放数据库中对应的字段,其中faulthanding_info是数据表的名字,id和keywords分别是表中的两个字段

@TableName(faulthanding_info)
@Data
@EqualsAndHashCode(callSuper=true)
public class FaultHanding extends BaseEntity{
    @TableId(value="id",type=IdType.ASSIGN_ID)
    private Long id;
    @TableField(value="keywords")
    private String keywords
}

2.service层,读取所有的keywords,使用HashMap的内置方法,得到每个字符对应的出现次数,将得到的map转化成list?使用sort排序,最后得到按照词频从高到低排序后的列表。可以参看代码的注释,有不对的地方可以指正。

@Service
public class FaultHandingServiceImpl extends ServiceImpl<FaultHandingMapper,FaultHanding> implements FaultHandingService {
 public  List<Map.Entry<String,Integer>> keywordMap(){
//把数据库中的所有数据都读出来,此时querywrapper是list类型,存的数据类似{[id1,keywords1],[id2,keywords2],[id3,keywords3],[id4,keywords4],[id5,keywords5]}
        LambdaQueryWrapper<FaultHanding> queryWrapper = new LambdaQueryWrapper<>();
        List<String> keywordList = CollectionUtil.newArrayList();
//有的数据的keywords是很多个,用中文逗号分割的,首先要读取数据库字段keywords下所有的数据,即把aa、b、cc、d都读出来,所以要foreach遍历querylist列表
        this.list(queryWrapper).forEach(faultHanding -> {
//先把含多个关键词的项按标点符号分割出来,例如分割前“aa,b,cc”这三项是一个字符串,使用split方法后,就把“aa,b,cc”这个字符串分成了“aa,b,cc”,分割后是三个字符串,aa、b、cc都是独立的,把每条数据的keywords都分割出来后,循环存放到list列表,此时list列表是没有去重复项的,list里的内容是这样的:["aa,b,cc","aa,cc","b","aa,d"]。
            List<String> list = CollectionUtil.newArrayList(faultHanding.getKeywords().split(","));
            list.forEach(e -> {
//循环遍历list列表["aa,b,cc","aa,cc","b","aa,d"],使用add方法存储到keywordList里,得到的keywordList是这样的["aa","b","cc","aa","cc","b","aa","d"]
                keywordList.add(e);
            });
        });
//定义一个map,字符串为key,出现次数为value。
        Map<String, Integer> map = new HashMap<>();
//遍历keywordList["aa","b","cc","aa","cc","b","aa","d"],此时的map是空的,所以先执行else中的语句。
        keywordList.forEach(i ->{
//如果map中包含i,map.get(i)得到value即该字符出现的次数,让其+1,使用push方法存到map中。
            if(map.containsKey(i)){
                map.put(i,map.get(i)+1);
            }else{
//map最开始为空,并不存在keywordList中的字符,所以keywordList中的每一项在map第一次遍历的时候,就作为map的key存到了map中,因此map的key是不重复的,其对应的value都是1,就像aa=1,b=1,cc=1,d=1
                map.put(i,1);
            }
//到此就得到了一个无序的map,里边存储了字符及其出现的次数,接下来对其从高到低排序
        });
//定义一个flag为false作为下边的判断条件,这块我参看网上的也不太清楚为什么,但是能运行出来。
        final boolean flag=false;
//定义一个新的列表info,搜map.entrySet()能看到info的定义是一种固定写法?通过getKey()得到K,getValue得到V
        List<Map.Entry<String,Integer>> info =new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
//使用Comparator对info进行排序,sort自动帮忙排序
        Collections.sort(info, new Comparator<Map.Entry<String, Integer>>() {
//重写了compare方法,我参考别人的,也不太懂,但他写的对。
            public int compare(Map.Entry<String, Integer> obj1, Map.Entry<String, Integer> obj2) {
                if (obj2.getValue() - obj1.getValue() != 0) {
                    return obj2.getValue() - obj1.getValue();
                } else {

                    if (flag) {
                        return obj1.getKey().compareTo(obj2.getKey());
                    } else {
                        return -(obj1.getKey().compareTo(obj2.getKey()));
                    }
                }
            }
        });
//得到的info就是按value排序后的列表,接下来把列表传到前端即可
        return info;
    }

}

3.service层接口

public interface FaultHandingService extends IService<FaultHanding>{
     List<Map.Entry<String,Integer>> keywordMap();
}

4.controller层

@RestController
@ApiResource(name = "故障知识库", path = "/faultHanding")
public class FaultHandingController {
@GetResource(name="获取关键词列表",path="/keywordMap", requiredLogin = false, requiredPermission = false)
public ResponseData keywordMap(){
    return new SuccessResponseData(faultHandingService.keywordMap());
}

到这里后端的内容就写好了,前端使用vscode

首先需要写一个js作为api,和后端的controller方法对应

代码如下,方法名要和controller的方法名一样,我这里都是keywordMap:

import Request from '@/utils/request';
export class faultHandingApi {
   static keywordMap(params){
    return Request.getAndLoadData('/faultHanding/keywordMap', params);
  } 
}

 前端使用a-tag标签,把内容做展示,新建一个vue,我的项目中要展示11项内容,所以slice方法写的11,根据情况自己修改就可以

<template>

<div style="text-align:center;margin-top:2%" >

         <a-space>

          <div v-for="(item, index) in keywordList.slice(0,11)" :key="index">

            <a-tag >

              <a>{{ Object.keys(item)[0]}}</a>

            </a-tag>

          </div>

         </a-space>

      </div>

</template>

<script>

import { faultHandingApi } from './faultHandingApi';

export default defineComponent({        

data() {

    return {

      keywordList:[],

    }

  },

 async created(){

    this.keywordList=await faultHandingApi.keywordMap();

  },

methods:{

},

})

</script>

由于我开发项目具有一定的保密性,因此数据库内容和文章中举例有不同,但方法是一样的,供大家参考,有问题一起探讨,不对的地方请指正,最后的效果图如下:搜索框下边的11个标签就是数据库中词频最高的几项

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现 excel 数据导入的功能,需要完成以下步骤: 1. 前端页面实现文件上传功能,可以使用 vue-upload-component 组件实现。 2. 后端使用 Spring Boot 框架,导入 poi 依赖,使用 poi 解析 Excel 文件,获取数据并保存到数据库中。 下面是具体的实现步骤: 1. 前端页面 在 vue 组件中,使用 vue-upload-component 组件实现文件上传功能。具体实现代码如下: ``` <template> <div> <input type="file" ref="file" @change="handleFileChange"> <button @click.prevent="submit">上传</button> </div> </template> <script> import UploadComponent from 'vue-upload-component' export default { components: { UploadComponent }, data () { return { file: null } }, methods: { handleFileChange () { this.file = this.$refs.file.files[0] }, submit () { const formData = new FormData() formData.append('file', this.file) this.$http.post('/upload', formData) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) } } } </script> ``` 2. 后端实现 2.1 添加依赖 在 Spring Boot 项目的 pom.xml 文件中添加 poi 依赖: ``` <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> ``` 2.2 实现文件上传接口 在 Spring Boot 项目中,实现文件上传的接口: ``` @PostMapping("/upload") public void upload(MultipartFile file) throws Exception { Workbook workbook = WorkbookFactory.create(file.getInputStream()); Sheet sheet = workbook.getSheetAt(0); List<Data> dataList = new ArrayList<>(); for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { continue; } Data data = new Data(); data.setName(row.getCell(0).getStringCellValue()); data.setAge((int) row.getCell(1).getNumericCellValue()); dataList.add(data); } dataRepository.saveAll(dataList); } ``` 其中,Data 是保存数据的实体类,dataRepository 是数据访问接口。 3. 完整示例 前端页面代码: ``` <template> <div> <input type="file" ref="file" @change="handleFileChange"> <button @click.prevent="submit">上传</button> </div> </template> <script> import UploadComponent from 'vue-upload-component' export default { components: { UploadComponent }, data () { return { file: null } }, methods: { handleFileChange () { this.file = this.$refs.file.files[0] }, submit () { const formData = new FormData() formData.append('file', this.file) this.$http.post('/upload', formData) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) } } } </script> ``` 后端代码: ``` @RestController public class ExcelController { @Autowired private DataRepository dataRepository; @PostMapping("/upload") public void upload(MultipartFile file) throws Exception { Workbook workbook = WorkbookFactory.create(file.getInputStream()); Sheet sheet = workbook.getSheetAt(0); List<Data> dataList = new ArrayList<>(); for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { continue; } Data data = new Data(); data.setName(row.getCell(0).getStringCellValue()); data.setAge((int) row.getCell(1).getNumericCellValue()); dataList.add(data); } dataRepository.saveAll(dataList); } } @Entity public class Data { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Integer age; // getter and setter } ``` 注意,需要在 application.properties 中配置数据库连接等信息。另外,需要在 Vue 项目中使用 axios 来发送请求。 这样,就完成了 Spring Boot + Vue 实现 excel 数据导入功能的示例。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值