为了账号安全,请及时绑定邮箱和手机立即绑定

分组字符串 - Java

分组字符串 - Java

收到一只叮咚 2021-10-28 09:29:31
我有一个 ArrayList。我想对相似的项目进行分组,这样 letter.pdf 是每个组中的第一个。例如:123_Letter.pdf123_Others.pdf123_More.pdf222_Second.pdf222_Letter.pdf222_Third.pdf222_Fourth.pdf123_File.pdf输出应该是:**123_Letter.pdf**123_Others.pdf123_More.pdf123_File.pdf**222_Letter.pdf**222_Second.pdf222_Third.pdf222_Fourth.pdf每组中其他元素的顺序无关紧要。列表中有 3000 多个元素。如您所见,仅排序并没有多大帮助。我试过这样的事情,但它缺少最后一个元素 123_File.pdf。有没有更好的方法来做到这一点?请帮忙。String root = list.get(0).substring(0,4);        ArrayList<String> al = new ArrayList<>();        for (int i = 0; i < list.size(); i++) {            while (list.get(i).substring(0, 4).equals(root)) {                if (list.get(i).endsWith("etter.pdf")) {                    al.add(0, list.get(i));                    i++;                } else {                    al.add(list.get(i));                    i++;                }            }            System.out.println(al);            al = new ArrayList<>();            root = list.get(i).substring(0, 4);        }
查看完整描述

3 回答

?
开满天机

TA贡献1786条经验 获得超13个赞

听起来您想根据两个标准进行排序:

  • 每个列表项中的前三个字符,以及

  • 每个列表项的其余内容,例如 Letter.pdf 首先出现。

一个老派的合理解决方案是实现 custom java.util.Comparator,并将其用作排序的基础:

public static List<String> sortOldSchool(List<String> list){


    Comparator<String> comparator = new Comparator<String>(){

        private static final String LETTER = "Letter.pdf";

        public int compare(String orange, String apple){

            String ostart = orange.substring(0,3);

            String astart = apple.substring(0,3);

            if (ostart.equals(astart)){

                if (orange.endsWith(LETTER)){

                    return (apple.endsWith(LETTER)) ? 0 : -1;

                }

                else return (apple.endsWith(LETTER)) ? 1 : orange.compareTo(apple);

            }

            else return ostart.compareTo(astart);

        }

    };

    Collections.sort(list, comparator);

    return list;

}

一种更现代的方法是利用从 Java 8 开始可用的新功能范式:


public static List<String> sortFunctional(List<String> list){


    Comparator<String> firstThree= Comparator.comparing(item -> item.substring(0,3));

    Comparator<String> letter = Comparator.comparing(item -> (!item.endsWith("Letter.pdf")));

    return list.stream()

            .sorted(firstThree.thenComparing(letter))

            .collect(Collectors.toList());

}    


查看完整回答
反对 回复 2021-10-28
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

根据您的描述 - 我建议将问题分解为两个子问题:

  • 步骤 1:将值组织到它们的前缀组中

  • 第 2 步:对每个前缀组中的值进行排序,确保值“_Letter.pdf”排在第一位。

我提供了一个代码示例来演示以下每个步骤:

import java.util.*;

import java.util.function.Function;

import java.util.stream.Collector;

import java.util.stream.Collectors;

import java.util.stream.Stream;


import static java.util.stream.Collectors.toList;


public class StackoverflowTest {


    List<String> values = Arrays.asList(

            "123_Letter.pdf",

            "123_Others.pdf",

            "123_More.pdf",

            "222_Second.pdf",

            "222_Letter.pdf",

            "222_Third.pdf",

            "222_Fourth.pdf",

            "123_File.pdf");


    List<String> expected = Arrays.asList(

            "123_Letter.pdf",

            "123_Others.pdf",

            "123_More.pdf",

            "123_File.pdf",

            "222_Letter.pdf",

            "222_Second.pdf",

            "222_Third.pdf",

            "222_Fourth.pdf"

    );


    @Test

    public void sort() {

        // Basic function to group the values by the prefix

        Collector<String, ?, Map<String, List<String>>> groupByPrefix = Collectors.groupingBy(c -> c.substring(0, 3));


        // Basic function to sort the groups with _Letter.pdf first

        Function<List<String>, Stream<? extends String>> sortPrefixGroups = v ->

                v.stream().sorted(Comparator.comparing(i -> !i.endsWith("_Letter.pdf")));


        // Step 1: Organise the values into their prefix groups

        Map<String, List<String>> groupedByPrefix = new TreeMap<>(values.stream().collect(groupByPrefix));



        // Step 2: Sort each of the prefix groups and recombine them back into a list to maintain their internal order

        List<String> collect = groupedByPrefix.entrySet().stream().map(Map.Entry::getValue).flatMap(sortPrefixGroups).collect(toList());


        Assert.assertEquals(expected, collect);

        //Print just for fun

        collect.forEach(System.out::println);

    }

}


查看完整回答
反对 回复 2021-10-28
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

如何使用HashMap:


HashMap<String, List<String>> hashMap = new HashMap<String, List<String>>();

现在,遍历哈希图并添加元素:


if (!hashMap.containsKey(listItem.substring(0,2)) {

    List<String> items = new ArrayList<String>();

    items.add(listItem);


    hashMap.put(listItem.substring(0,2), items);

} else {

    hashMap.get(listItem.substring(0,2)).add(items);

}


查看完整回答
反对 回复 2021-10-28
  • 3 回答
  • 0 关注
  • 171 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信