2015-11-12 3 views
1

Допустим, у меня есть две коллекции под названием desiredCompanies как массив и companiesSource как Список компаний:Сортировка на основе другой коллекции в Java

List<String> desiredCompanies = Arrays.asList("AAA", "AAB", "AAC"); 

    List<Company> companiesSource = new ArrayList<Company>(); 

    Company item1= new Company(); 
    item1.setCode("AAB"); 
    item1.setPercent(200); 
    item1.setLocation("America"); 
    companiesSource.add(item1); 

    Company item2= new Company(); 
    item2.setCode("AAX"); 
    item2.setPercent(900); 
    item2.setLocation("Africa"); 
    companiesSource.add(item2); 

    Company item3= new Company(); 
    item3.setCode("AAC"); 
    item3.setPercent(900); 
    item3.setLocation("Singapore"); 
    companiesSource.add(item3); 

    Company item4= new Company(); 
    item4.setCode("AAA"); 
    item4.setPercent(900); 
    item4.setLocation("Singapore"); 
    companiesSource.add(item4); 

    Company item5= new Company(); 
    item5.setCode("AAR"); 
    item5.setPercent(900); 
    item5.setLocation("Japan"); 
    companiesSource.add(item5); 

Я хотел бы получить результирующий список с новым списком компаний или сортировать существующие компанииSource как в порядке желаемых компаний, которые должны содержать только этот элемент, в списке желаемых компаний.

+3

Вы бы создать 'Comparator', сравнивающие Компании, основанные на' desiredCompanies.indexOf (company.getCode()) '. Полный ответ доступен здесь: [Компаратор основан на настраиваемом порядке] (http://stackoverflow.com/questions/5477511/comparator-based-on-a-configurable-orderl). – aioobe

+0

'' wantedCompanies'' не содержит '' 'AAR' '' и '' "AAX" '', для правильной сортировки нам нужны детали ... –

+1

Будет ли когда-нибудь повторяющийся код? Например, более чем одна компания «AAR»? – matt

ответ

1

Если вы хотите, чтобы отсортированный список имел элемент для каждого из кодов в желаемых компаниях, тогда этот код сделает это. Это будет иметь нулевое значение в SortedList для несуществующего кода в companiesSources

List<Company> sortedList = new ArrayList<>(); 
Map<String, Company> map = new HashMap<>(); 
for(Company company : companiesSource){ 
    map.put(company.getCode(), company); 
} 
for(String desired : desiredCompanies){  
    sortedList.add(map.get(desired)); 
} 

В вы хотите, чтобы избежать null значения в отсортированной коллекции для несуществующих Company refereces из desiredCompanies, используйте код ниже:

List<Company> sortedList = new ArrayList<Company>(); 
Map<String, Company> map = new HashMap<>(); 
for(Company company : companiesSource) { 
    map.put(company.getCode(), company); 
} 
for(String desired : desiredCompanies) { 
    if(map.get(desired) != null) { 
     sortedList.add(map.get(desired)); 
    } 
} 
+0

'sortedList.add (map.get (желательно));' добавит некоторые значения «null» в коллекцию. – Zilvinas

+0

@ Zilvinas только для несуществующих балансовых единиц в '' wishCompanies'' он добавит указатели '' null'' –

+0

Согласен с @Zilvinas – Bulu

0

Если вы уверены, что code всегда является строкой, вы можете использовать indexOf, чтобы получить заказ (не очень эффективный, хотя):

final List<String> desiredCompanies = Arrays.asList("AAA", "AAB", "AAC"); 

    List<Company> companiesSource = new ArrayList<Company>(); 

    /* compute & remove unneeded values here */ 

    Collections.sort(companiesSource, new Comparator<Company>() { 
     @Override 
     public int compare(Company o1, Company o2) { 
      int order1 = desiredCompanies.indexOf(o1.getCode()); 
      int order2 = desiredCompanies.indexOf(o2.getCode()); 
      return Integer.signum(order1 - order2); 
     } 
    }); 

Чтобы сделать это более эффективным, вы можете предварительно рассчитать заказы в набор пыльников.

+1

Почему бы вам просто не использовать ['' String # compareTo (String) ''] (http://docs.oracle.com/javase/8/docs/api/java /lang/String.html#compareTo-java.lang.String-) вместо этого? –

+0

@BinkanSalaryman сравнить что? Мы сравниваем порядок строк (кодов) в списке, никто не сказал, что они будут изначально отсортированы. – Zilvinas

+0

'' Collections.sort (companiesSource, (o1, o2) -> o2.getCode().compareTo (o1.getCode())); '', поскольку '' желательные компании'', похоже, отражают сортировку по алфавиту ... –

0

Java 8 стиль:

List<Company> sortedDesiredCompanies = companiesSource.stream() 
    .filter(c -> desiredCompanies.contains(c.getCode())).sort() 
    .collect(Collectors.toList()); 
+0

Я после Java 7 – Bulu

+0

, очевидно, Java 8 имеет плохое форматирование и меньше объяснений ...: P –

+0

Это не отсортировано по заказу 'желаемых компаний' по запросу –

0

Вы могли бы отфильтровать компании на основе их кода, находящегося в го e companiesSource. Затем вы можете отсортировать их в соответствии с индексом этого кода, реализовав свой собственный Comparator, а затем объедините все вместе с API-интерфейсами Java 8.

The Comparator:

public class DesirabilityComparator implements Comparator<Company> { 
     private List<String> desiredCompanies; 
     public DesirabilityComparator(List<String> desiredCompanies) { 
      this.desiredCompanies = desiredCompanies; 
     } 

     @Override 
     public int compare(Company c1, Company c2) { 
      return Integer.compare(desiredCompanies.indexOf(c1.getCode()), 
            desiredCompanies.indexOf(c2.getCode())); 
     } 
    } 

Собираем все вместе:

List<Company> sortedAndFilteredCompanies = 
     companiesSource.stream() 
         .filter(c -> desiredCompanies.contains(c.getCode())) 
         .sorted(new DesirabilityComparator(desiredCompanies)) 
         .collect(Collectors.toList()); 

EDIT:
Как aioobe прокомментировал это можно сделать гораздо более элегантно с Comparator.comparing:

List<Company> sortedAndFilteredCompanies = 
     companiesSource.stream() 
         .filter(c -> desiredCompanies.contains(c.getCode())) 
         .sorted(Comparator.comparing(c -> desiredCompanies.indexOf(c.getCode())) 
         .collect(Collectors.toList()); 
+0

Вы должны иметь возможность заменить весь' DesirabilityComparator' на 'Comparator.comparing' (c -> wishCompanies.indexOf (c.getCode()). – aioobe

+0

@ aioobe хорошая точка, спасибо! Все еще привык к Java 8 ... Я отредактирую это в ответ. – Mureinik

0

Хотя это probabl у не продуктивный код, я предлагаю разбив код на логические единицы, например .:

public static void main(String[] args) { 
    // register companies by their codes to look them up 
    // alternativly, you can implement this in a ``Company(String code)`` constructor 
    // along with a static accessible registry map in ``Company`` 
    Map<String, Company> companyRegistry = new HashMap<>(); 
    for(Company c : getCompanies()) { 
     companyRegistry.put(c.getCode(), c); 
    } 

    // execute query on model and print out results 
    System.out.println(queryCompanies(companyRegistry, "AAA", "AAB", "AAC")); 
} 

static List<Company> getCompanies() { 
    // collect all companies you are going to use later 
    List<Company> result = new ArrayList<>(); 
    Company c; 

    // better add a constructor/factory method as shortcut 
    // or load the objects from a database 
    result.add(c = new Company()); 
    c.setCode("AAB"); 
    c.setPercent(200); 
    c.setLocation("America"); 

    result.add(c = new Company()); 
    c.setCode("AAX"); 
    c.setPercent(900); 
    c.setLocation("Africa"); 

    result.add(c = new Company()); 
    c.setCode("AAC"); 
    c.setPercent(900); 
    c.setLocation("Singapore"); 

    result.add(c = new Company()); 
    c.setCode("AAA"); 
    c.setPercent(900); 
    c.setLocation("Singapore"); 

    result.add(c = new Company()); 
    c.setCode("AAR"); 
    c.setPercent(900); 
    c.setLocation("Japan"); 

    return result; 
} 

static List<Company> queryCompanies(Map<String, Company> companyRegistry, String... desiredCompanies) { 
    // add "-ea" as VM-option to enable assertions 
    // this is just a friendly check to avoid duplicates, you may remove it 
    assert new HashSet<>(Arrays.asList(desiredCompanies)).size() == desiredCompanies.length : "desiredCompany contains duplicates"; 

    List<Company> result = new ArrayList<>((int)desiredCompanies.length); 

    for(String desiredCompany : desiredCompanies) { 
     Company desired = companyRegistry.get(desiredCompany); 
     if(desired != null) { 
      result.add(desired); 
     } 
    } 
    return result; 
} 
Смежные вопросы