Сортировка элементов ArrayList по имени

Я пытаюсь переставить ArrayList на основе имени элементов, которые должны быть в определенном индексе.

Мой список в настоящее время это:

"SL"
"TA"
"VP"
"SP"
"PR"

и я хочу переставить их на:

"SL"
"SP"
"TA"
"PR"
"VP"

но на основе имени и не в индексе.

Я пробовал это:

for (int i=0; i< list.size(); i++){
    if (list.get(i).getCategoryName().equals("SL")){
        orderedDummyJSONModelList.add(list.get(i));
    }
}
for (int i=0; i< list.size(); i++){
    if (list.get(i).getCategoryName().equals("SP")){
        orderedDummyJSONModelList.add(list.get(i));
    }
}
for (int i=0; i< list.size(); i++){
    if (list.get(i).getCategoryName().equals("TA")){
        orderedDummyJSONModelList.add(list.get(i));
    }
}
for (int i=0; i< list.size(); i++){
    if (list.get(i).getCategoryName().equals("PR")){
        orderedDummyJSONModelList.add(list.get(i));
    }
}
for (int i=0; i< list.size(); i++){
    if (list.get(i).getCategoryName().equals("VP")){
       orderedDummyJSONModelList.add(list.get(i));
    }
}

и это работает хорошо, но я хочу знать, есть ли более эффективный способ сделать в 1 для цикла или, возможно, функции. Я не хочу делать это так:

orderedDummyJSONModelList.add(list.get(0));
orderedDummyJSONModelList.add(list.get(3));
orderedDummyJSONModelList.add(list.get(1));
orderedDummyJSONModelList.add(list.get(4));
orderedDummyJSONModelList.add(list.get(2));

Что тоже работает. Есть идеи?

8 ответов

  1. Вы можете использовать Collection.Sortметод как Collection.Sort(list)так listкак List<String>вы будете в порядке. Но если вы хотите реализовать новый компаратор:

    Collections.sort(list, new NameComparator());
    
    class NameComparator implements Comparator<String> { //You can use classes
        @Override
        public int compare(String a, String b) { //You can use classes
            return a.compareTo(b); 
        }
    }
    

    РЕДАКТИРОВАТЬ:

    Вы можете определить компаратор классов для ваших потребностей:

    class ClassComparator implements Comparator<YourClass> { //You can use classes
        @Override
        public int compare(YourClass a, YourClass b) { //You can use classes
            return a.name.compareTo(b.name); 
        }
    }
    
  2. Ключевая вещь здесь: вам нужно получить ясным на ваших требованиях .

    Другими словами: конечно, можно перетасовать объекты, хранящиеся в списке. Но: вероятно, вы хотите сделать это программно .

    Другими словами: правильный подход заключается в использовании встроенных механизмов сортировки коллекции, но с предоставлением пользовательского компаратора.

    Смысл: вам лучше найти алгоритм, который определяет, как исходить из

    «SL»
    «ТЕХНИЧЕСКАЯ ПОМОЩЬ»
    «ВИЦЕ»
    «SP»
    «ПИАР»

    к

    «SL»
    «SP»
    «ТЕХНИЧЕСКАЯ ПОМОЩЬ»
    «ПИАР»
    «ВИЦЕ»

    Этот алгоритм должен войти в вашу реализацию компаратора!

    Дело в том, что у вас есть некоторые List<X>в первую очередь. И X объекты предоставляют какой-то метод для извлечения тех строк, которые вы показываете здесь. Таким образом, вы должны создать aComparator<X>, который работает на значениях X; и использует некоторое среднее, чтобы добраться до этих строковых значений; и на основе этого вы решаете, является ли X1<, = или>, чем некоторый объект X2!

    1. Используйте hashmap для хранения веса всех строк (чем больше значение hashmap, тем позже эта строка должна появиться в конечном списке).
    2. Используя хэш-карту, вы можете развернуть ее позже и для других строк. В будущем это будет легче улучшить.
    3. Наконец, используйте пользовательский компаратор для этого.

    Необходимая Настройка:

           List<String> listOfStrings = Arrays.asList("SL", "TA", "VP", "SP", "PR");
    
            HashMap<String, Integer> sortOrder = new HashMap<>();
            sortOrder.put("SL", 0);
            sortOrder.put("TA", 1);
            sortOrder.put("VP", 2);
            sortOrder.put("SP", 3);
            sortOrder.put("PR", 4);
    

    Стримы:

            List<String> sortedList = listOfStrings.stream().sorted((a, b) -> {
                return Integer.compare(sortOrder.get(a), sortOrder.get(b));
            }).collect(Collectors.toList());
    
            System.out.println(sortedList);
    

    Non-Поток:

            Collections.sort(listOfStrings, (a, b) -> {
                return Integer.compare(sortOrder.get(a), sortOrder.get(b));
            });
    OR
            listOfStrings.sort((a, b) -> {
                return Integer.compare(sortOrder.get(a), sortOrder.get(b));
            });
    
            System.out.println(listOfStrings);
    

    Выход:

    [SL, TA, VP, SP, PR]
    
  3. здесь ответ как раз специфический для вашей проблемы работая как раз для данного выхода. Если Listсодержит что-то еще, это может нарушить ваш заказ, так как нет никакого правила о том, как его заказать, и PRпросто случайным образом появляется в конце.

    public static void main(String[] args) {
        List<String> justSomeNoRuleOrderingWithARandomPRInside = new ArrayList<String>();
        justSomeNoRuleOrderingWithARandomPRInside.add("SL");
        justSomeNoRuleOrderingWithARandomPRInside.add("TA");
        justSomeNoRuleOrderingWithARandomPRInside.add("VP");
        justSomeNoRuleOrderingWithARandomPRInside.add("SP");
        justSomeNoRuleOrderingWithARandomPRInside.add("PR");
        java.util.Collections.sort(justSomeNoRuleOrderingWithARandomPRInside, new NameComparator());
        for(String s : justSomeNoRuleOrderingWithARandomPRInside) {
            System.out.println(s);
        }
    }
    
    static class NameComparator implements Comparator<String> { //You can use classes
        @Override
        public int compare(String a, String b) { //You can use classes
            // Lets just add a T in front to make the VP appear at the end 
            // after TA, because why not
            if (a.equals("PR")) {
                a = "T"+a;
            } else if(b.equals("PR")) {
                b = "T"+b;
            }
            return a.compareTo(b);
        }
    }
    

    O/P

    SL
    SP
    TA
    PR
    VP
    

    Но, честно говоря, это решение-дерьмо, и без какого-либо четкого правила о том, как их заказать, это будет обречено на неудачу, как только вы что-то измените, как @GhostCat пытался объяснить.

  4. Как насчет этого

    // define the order
    List<String> ORDER = Arrays.asList("SL", "SP", "TA", "PR", "VP");
    
    List<MyObject> list = ...
    list.sort((a, b) -> {
        // lamba syntax for a Comparator<MyObject>
        return Integer.compare(ORDER.indexOf(a.getString()), ORDER.indexOf(b.getString());
    });
    

    Обратите внимание, что при этом все строки, не определенные в списке заказов, будут помещены в начало отсортированного списка. Это может быть или не может быть приемлемым — возможно, стоит проверить, что только допустимые строки (т. е. члены заказа) появляются в результате MyObject.getString ().

  5. Карту индекса можно построить с помощью a LinkedHashMap. Это будет использоваться для поиска порядка сортировки с использованием имен категорий товаров.

    ItemSorting

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class ItemSorting {
        public static void main(String[] args) {
            List<Item> list = new ArrayList<Item>();
            IndexMap indexMap = new IndexMap("SL", "SP", "TA", "PR", "VP");
            ItemComparator itemComparator = new ItemComparator(indexMap);
    
            list.add(new Item("SL"));
            list.add(new Item("TA"));
            list.add(new Item("VP"));
            list.add(new Item("SP"));
            list.add(new Item("PR"));
    
            Collections.sort(list, itemComparator);
    
            for (Item item : list) {
                System.out.println(item);
            }
        }
    }
    

    ItemComparator

    import java.util.Comparator;
    
    public class ItemComparator implements Comparator<Item> {
        private IndexMap indexMap;
    
        public IndexMap getIndexMap() {
            return indexMap;
        }
    
        public void setIndexMap(IndexMap indexMap) {
            this.indexMap = indexMap;
        }
    
        public ItemComparator(IndexMap indexMap) {
            this.indexMap = indexMap;
        }
    
        @Override
        public int compare(Item itemA, Item itemB) {
            if (itemB == null) return -1;
            if (itemA == null) return 1;
            if (itemA.equals(itemB)) return 0;
    
            Integer valA = indexMap.get(itemA.getCategoryName());
            Integer valB = indexMap.get(itemB.getCategoryName());
    
            if (valB == null) return -1;
            if (valA == null) return 1;
    
            return valA.compareTo(valB);
        }
    }
    

    IndexMap

    import java.util.LinkedHashMap;
    
    public class IndexMap extends LinkedHashMap<String, Integer> {
        private static final long serialVersionUID = 7891095847767899453L;
    
        public IndexMap(String... indicies) {
            super();
    
            if (indicies != null) {
                for (int i = 0; i < indicies.length; i++) {
                    this.put(indicies[i], new Integer(i));
                }
            }
        }
    }
    

    Пункт

    public class Item {
        private String categoryName;
    
        public Item(String categoryName) {
            super();
            this.categoryName = categoryName;
        }
    
        public String getCategoryName() {
            return categoryName;
        }
    
        public void setCategoryName(String categoryName) {
            this.categoryName = categoryName;
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((categoryName == null) ? 0 : categoryName.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            Item other = (Item) obj;
            if (categoryName == null) {
                if (other.categoryName != null) return false;
            } else if (!categoryName.equals(other.categoryName)) return false;
            return true;
        }
    
        @Override
        public String toString() {
            return String.format("Item { \"categoryName\" : \"%s\" }", categoryName);
        }
    }
    

    Результат

    Item { "categoryName" : "SL" }
    Item { "categoryName" : "SP" }
    Item { "categoryName" : "TA" }
    Item { "categoryName" : "PR" }
    Item { "categoryName" : "VP" }
    
  6. Вы можете создать карту, которая поддерживает позицию. При итерации через неупорядоченный список просто получить позицию этого строкового значения и вставить в новый массив(не arraylist), то позже, если требуется, вы можете преобразовать этот массив в ArrayList.
    Пример кода:

    Map<String,Integer> map = new HashMap<>(); //you can may be loop through and make this map
    map.put("SL", 0);
    map.put("SP", 1);
    map.put("TA",2);
    map.put("PR",3);
    map.put("VP",3);
    List<String> list1 // your unordered list with values in random order
    String[] newArr =  new String[list1.size()];
    for(String strName: list1){
        int position  = map.get(strName);
        arr[position] = strName;
    }
    //newArr has ordered result.
    
  7. Можно определить вспомогательный метод, подобный этому:

    public static int get(String name) {
        switch (name) {
        case "SL":
            return 1;
        case "SP":
            return 2;
        case "TA":
            return 3;
        case "PR":
            return 4;
        case "VP":
            return 5;
        default:
            return 6;
        }
    }
    

    и напишите в вашем основном методе что-то вроде:

    ArrayList<String> al = new ArrayList<>();
    al.add("SL");
    al.add("TA");
    al.add("VP");
    al.add("SP");
    al.add("PR");
    Collections.sort(al, (o1, o2) -> return get(o1) - get(o2); );
    al.forEach((s) -> System.out.println(s));