递归淘汰List集合头部数据,获取最终集合的起始坐标

简介: 递归淘汰List集合头部数据,获取最终集合的起始坐标

需求分析:

场景:调用三方chatGPT服务,通过传递历史聊天记录来获得联系上下文的回答

需要解决的问题:传递的历史聊天记录有限制,所以每次就需要去判断是否超出限制,如果超出限制就要淘汰掉一些最早的聊天记录去传值。

数据结构(简化):定义一个集合,集合中的对象有两个属性,一个是聊天内容,一个是聊天内容的字数

分析:如果传递的数据>设定的最大值,这个时候我们把两者的差计算出来定义为A,然后去聊天记录的集合的开始去判断A是否小于集合中第一个元素设定的字数,如果小于那把这个元素从集合中移除就行了,如果不小于,那就需要拿到集合的前两个元素设定的字数加起来,再和A去判断,以此类推

使用递归算法获取淘汰集合的临界坐标:

温馨提示:注释都放到代码里了哦~

/**
     * 淘汰老的聊天记录
     * @param  num 是集合总字数和设定限制的差值
     * @param  s 是最后要返回的临界值,也就是s前面的坐标都要被淘汰
     */
    int weedOut(int num, int s, List<ChatMessage> chatMessageList) {
        int sum = 0; // 集合聊天记录最前面部分tokens相加
        for (int i = 0; i < s; i++) {
            ChatMessage chatMessages = chatMessageList.get(i);
            // 计算要淘汰的元素的字数
            sum += chatMessages.getTokens();
        }
        // 判断要淘汰的元素的字数,如果不符合条件  下标继续下移  s + 1
        if (sum > num) {
            return s; // 最后要这个集合下标为s后面的
        } else {
            return weedOut(num, s + 1, chatMessageList);
        }
    }

结合业务的完整代码供大家交流:

/**
 * @author : jiagang
 * @date : Created in 2023/7/12 10:48
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ChatTest {
    @Autowired
    private ChatMessageService chatMessageService;
    @Test
    public void test1(){
        List<ChatMessage> chatMessageList = chatMessageService.chatMessageList(ChatMessage.builder().sessionId("f3667fec-ff71-f1e9-108a-658f527378a3").build());
        JSONArray jsonArray = new JSONArray(); // 最终结果
        if (!CollectionUtils.isEmpty(chatMessageList)) {
            // 计算聊天信息tokens
            int sum = chatMessageList.stream().mapToInt(ChatMessage::getTokens).sum(); // 301 个   99    202
            if (sum > VoiceChatConstant.TOKENS) {
                // 获取淘汰集合坐标的临界点
                int index = weedOut(sum - VoiceChatConstant.TOKENS, 1, chatMessageList);
                System.out.println("获取到的临界点下标---->" + index);
                for (int i = index; i < chatMessageList.size();i ++){
                    ChatMessage chatMessage = chatMessageList.get(i);
                    JSONObject jsonObject = new JSONObject();
                    //jsonObject.put("id",chatMessage.getId());
                    jsonObject.put("role",chatMessage.getSenderCode().equals(VoiceChatConstant.CHAT_CODE) ? VoiceChatConstant.CHAT_CODE : VoiceChatConstant.USER_CODE);
                    jsonObject.put("content",chatMessage.getMessage());
                    jsonArray.add(jsonObject);
                }
            } else {
                chatMessageList.forEach(c ->{
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("role", c.getSenderCode().equals(VoiceChatConstant.CHAT_CODE) ? VoiceChatConstant.CHAT_CODE : VoiceChatConstant.USER_CODE);
                    jsonObject.put("content", c.getMessage());
                    jsonArray.add(jsonObject);
                });
            }
        }
        System.out.println(jsonArray);
    }
    /**
     * 淘汰老的聊天记录
     * @param  num 是集合总字数和设定限制的差值
     * @param  s 是最后要返回的临界值,也就是s前面的坐标都要被淘汰
     */
    int weedOut(int num, int s, List<ChatMessage> chatMessageList) {
        int sum = 0; // 集合聊天记录最前面部分tokens相加
        for (int i = 0; i < s; i++) {
            ChatMessage chatMessages = chatMessageList.get(i);
            // 计算要淘汰的元素的字数
            sum += chatMessages.getTokens();
        }
        // 判断要淘汰的元素的字数,如果不符合条件  下标继续下移  s + 1
        if (sum > num) {
            return s; // 最后要这个集合下标为s后面的
        } else {
            return weedOut(num, s + 1, chatMessageList);
        }
    }
}

分割线-----------------------------------------------------------------------------------------------------------------------------------------------------------

创作不易,三连支持一下吧 👍

最后的最后送大家一句话

白驹过隙,沧海桑田

相关文章
|
9天前
|
Dart
Dart之集合详解(List、Set、Map)
Dart之集合详解(List、Set、Map)
14 1
|
9天前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
12 1
|
21天前
|
索引
List集合(方法简介,集合遍历)
List集合(方法简介,集合遍历)
|
9天前
|
存储 消息中间件 算法
Java中的集合框架详解:List、Set、Map的使用场景
Java中的集合框架详解:List、Set、Map的使用场景
|
3天前
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
|
7天前
|
存储 API Kotlin
Kotlin中的List集合
Kotlin中的List集合
13 2
|
17天前
|
存储 Java 索引
告别Java集合小白!一文读懂List的精髓
【6月更文挑战第17天】Java中的List接口作为有序集合,允许存储和操作有序元素,支持重复值。ArrayList和LinkedList是常见实现类:ArrayList基于数组,适合快速访问但插入删除慢;LinkedList基于链表,插入删除快但访问慢。了解其核心概念、方法及泛型使用,能提升编程效率和代码质量。示例代码展示了添加和访问元素。通过深入学习,可以更好地掌握List的高级用法。
|
23天前
|
存储 安全 Java
Java集合详解:Set, Map, Vector, List的对比与联系
Java集合框架核心包括List、Set、Map和Vector。List允许重复元素,如ArrayList(适合读取)和LinkedList(适合插入删除)。Set不允许重复,有HashSet(无序)和TreeSet(排序)。Map存储键值对,HashMap(无序)和TreeMap(排序)。Vector是线程安全的ArrayList替代品,但在多线程环境下使用。选择集合类型应根据应用场景,如有序、无序、键值对需求及线程安全考虑。
|
1天前
|
存储 语音技术 Python
语音识别,函数综合案例,黑马ATM,/t/t一个对不齐,用两个/t,数据容器入门,数据容器可以分为列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
语音识别,函数综合案例,黑马ATM,/t/t一个对不齐,用两个/t,数据容器入门,数据容器可以分为列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
|
26天前
|
存储 安全 Java
Java 集合(List、Set、Map 等)相关问答归纳再整理
HashMap 中使用键对象来计算 hashcode 值 HashSet 使用成员对象来计算 hashcode 值,对于两个对象来说hashcode 可能相同,所以 equals() 方法用来判断对象的相等性,如果两个对象不同的话,那么返回 false。 HashMap 比较快,因为是使用唯一的键来获取对象,HashSet 较 HashMap 来说比较慢。 4.1.3 HashMap 与 TreeMap
13 2