LINUX.ORG.RU

[java] Comparator

 


0

1

Здравствуйте!
Собирается статистика в виде записей Record: (pid, metrics_id, value), где pid - id'шник проекта, metrics_id - id'шник метрики, value - значение метрики.
Т.к. важна статистика именно для проекта в целом, то она собирается следующим образом:
Сначала для каждого проекта собираются все Record'ы и добавляются в ArrayList, например: ((1, 1, 23),(1, 2, 2)) - для проекта 1, значение метрики 1 равно 23, а метрики 2 - 2м.
И так для каждого проекта. Затем все эти ArrayList'ы объединяются в один ArrayList.
Получается ArrayList<ArrayList<Record>>.

Как лучше всего отсортировать конечный ArrayList по выбранной метрике?
Допустим, хочу отсортировать всю статистику по метрике с metrics_id = 2, по возрастанию.
Т.е. вызываю некоторую функцию Sort(ArrayList<ArrayList<Record>> stats, int metrics_id, boolean order_asc), которая возвращает новый ArrayList<ArrayList<Record>>, отсортированный по заданной метрике и в заданном порядке.

Как лучше всего это сделать? Можно ли это реализовать через Comparator/Comparable?
Что делать, если значения метрик будут не int, а float?

★★★★★

Я так понимаю, что через реализацию интерфейса Comparable для класса Record сделать не получится - ведь сравниваются не экземпляры самого класса, а ArrayList'ы, содержащие экземпляры. Т.е. надо либо через Comparator, либо самому изобретать велоси^Wфункцию?

kovrik ★★★★★
() автор топика
Ответ на: комментарий от kovrik

20 раз перечитал пока понял что хотите. Я бы на вашем месте архитектуру пересмотрел как то кучеряво получается.

Засуньте все Record в одну коллекцию (pid то есть в каждом Record можно всегда отфильтровать) и сортируйте потом как хотите через Comparator.

grassmeister
()

Как-то так...

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import com.ulcjava.base.shared.internal.IllegalArgumentException;

public class ComparatorTest {
	private static final int NUM_PROJECTS = 5;
	private static final int NUM_METRICS = 3;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List<List<Record>> myList = new ArrayList<List<Record>>();
		Random r = new Random();

		generateNewList(myList, r);

		Collections.sort(myList, new RecordComparator(1, true));
		System.out.println(myList);
		Collections.sort(myList, new RecordComparator(1, false));
		System.out.println(myList);
		Collections.sort(myList, new RecordComparator(2, true));
		System.out.println(myList);
		Collections.sort(myList, new RecordComparator(2, false));
		System.out.println(myList);
		//so on...

	}

	private static void generateNewList(List<List<Record>> myList, Random r) {
		//now the dragon eat me for index starting at 1... ah, no, this dragon is still hunting authors of JDBC
		for (int projId = 1; projId <= NUM_PROJECTS; projId++) {
			List<Record> project = new ArrayList<Record>(10);
			for (int metricsId = 1; metricsId <= NUM_METRICS; metricsId++) {
				project.add(new Record(projId, metricsId, r.nextFloat()));
			}
			myList.add(project);
		}
	}

	public static class RecordComparator implements java.util.Comparator<List<Record>> {
		private final int metricsId;
		private final boolean ascending;

		public RecordComparator(int metricsId, boolean ascending) {
			this.metricsId = metricsId;
			this.ascending = ascending;
		}

		@Override
		public int compare(List<Record> project1, List<Record> project2) {
			int compare = Float.compare(findMetricsValue(project1, metricsId), findMetricsValue(project2, metricsId));
			if (ascending) {
				return compare;
			} else {
				return -compare;
			}
		}

		private static float findMetricsValue(List<Record> project, int metricsId) {
			for (Record oneRecord : project) {
				if (oneRecord.metrics == metricsId) {
					return oneRecord.value;
				}
			}
			throw new IllegalArgumentException("No metrics " + metricsId + "in record" + project);
		}

	}

	public static class Record {

		private final int id;
		private final int metrics;
		private final float value;

		public Record(int id, int metrics, float value) {
			this.id = id;
			this.metrics = metrics;
			this.value = value;
		}

		@Override
		public String toString() {
			return "(" + id + "," + metrics + "," + value + ")";
		}

	}

}

moradan
()
Ответ на: комментарий от moradan

мм, я тут написал отдельные компараторы для каждой метрики, но ваше решение вроде более логично и правильно. Спасибо, сейчас попробую!

kovrik ★★★★★
() автор топика
Ответ на: комментарий от moradan

Все работает, спасибо большое! Запишу это решение.

kovrik ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.