не кидайтесь тапками плиз, превратилась совсем в говнокодершу. может, старость.
есть такой код:
for (ListIterator<Double> it = list.listIterator(); it.hasNext(); ) {
Double value = it.next();
Double refValue = null;
if (value != 0) {
if (value < 0 && it.hasNext()) {
refValue = it.next();
it.previous();
} else if (value > 0 && it.hasPrevious()) {
it.previous();
refValue = it.previous();
it.next();
it.next();
}
}
... //какие-то операции с value и refValue
}
што он делает — проходится по отсортированному списку из чисел (вида -100, -90, -2, 0, 3, 50) , и для каждого из чисел (кроме центрального — 0) находит "пару" — в зависимости оттого если число отрицательное или положительное — это или следующее число в списке, либо предыдущее. ноля быть не может. зачем такое надо не спрашивайте !!
вопрос — как переписать этот уродский код чтоб было красивее. одобряется использование фич джавы 8 — если они тут подойдут
Здравствуйте, зиг, Вы писали:
зиг>вопрос — как переписать этот уродский код чтоб было красивее. одобряется использование фич джавы 8 — если они тут подойдут
java8 стримы работают с текущим значением, там нет "предыдущего" и "следующего", так, что я бы даже отказался от итераторов. Не сказал бы, что короче, но на мой вкус читабельнее:
public static void main(String... args) {
List<Integer> ints = Arrays.asList(-100, -90, -2, 0, 3, 50);
for(int i = 0; i != ints.size(); ++i) {
Integer value = ints.get(i);
Integer refVal = getRefVal(value,
i != 0 ? ints.get(i-1) : null,
i != ints.size()-1 ? ints.get(i+1) : null);
System.out.println("value: " + value + ", refVal: " + refVal);
}
}
private static Integer getRefVal(Integer cur, Integer prev, Integer next) {
Integer result = null;
if ( cur < 0 && next != null ) {
result = next;
} else if ( cur > 0 && prev != null ) {
result = prev;
}
return result;
}
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>ИМХО из всех предложенных вариантов твой — самый читабельный. SVZ>Оставь как есть.
Читаемым он бы был, если бы не куча проверок на пограничные условия.
Здравствуйте, зиг, Вы писали:
зиг>што он делает — проходится по отсортированному списку из чисел (вида -100, -90, -2, 0, 3, 50) , и для каждого из чисел (кроме центрального — 0) находит "пару" — в зависимости оттого если число отрицательное или положительное — это или следующее число в списке, либо предыдущее. ноля быть не может. зачем такое надо не спрашивайте !!
зиг>вопрос — как переписать этот уродский код чтоб было красивее. одобряется использование фич джавы 8 — если они тут подойдут
А так нельзя?
int ap=0; double[] ac=new double[2];
for (ListIterator<Double> it = list.listIterator(); it.hasNext(); ac[0]=ac[1]) {
ac[ap]=it.next(); if (ap<1) { ap=1; continue; }
if (ac[1]<0) output(ac[1],ac[0]);
if (ac[0]>0) output(ac[0],ac[1]);
}
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>>ИМХО из всех предложенных вариантов твой — самый читабельный. SVZ>>Оставь как есть. B>Читаемым он бы был, если бы не куча проверок на пограничные условия.
Меня скорее все эти next() & prev() в разных последовательностях заставляют немного напрячься.
Здравствуйте, зиг, Вы писали:
зиг>есть такой код:
Этот код, кстати, падает если входной массив содержит только положительные числа. Это так и должно быть??
Я бы написал тупо как есть:
private static void doStuff(final List<Double> list) {
Double previous = null;
for (final ListIterator<Double> it = list.listIterator(); it.hasNext(); ) {
final Double value = it.next();
final Double refValue;
if (value < 0) {
refValue = peekNext(it);
} else if (value > 0) {
refValue = previous;
} else {
refValue = null;
}
previous = value;
... //какие-то операции с value и refValue
}
}
private static Double peekNext(final ListIterator<Double> it) {
if(!it.hasNext()) return null;
final Double val = it.next();
it.previous();
return val;
}
Этот код, кстати, не падает.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Предполагаю, что у нас вначале не итератор, а коллекция, и дополнительно добавил граничные условия.
По существу здесь 4 метода:
1) преобразование из итератора в коллекцию с нормальными граничными условиями (в конце null чтоб не делать дополнительный if). Это не писал, ибо лень;
2) Из этой коллекции возвращаю пары value — refValue. В качестве пар заюзал обычный массив, в других языках вернул бы кортеж или пару как тип. Причем вернул как стрим, он ленивый;
3) Вычисление refvalue в отдельный метод вынес — тоже можно тестить отдельно;
3) собственно сама логика, которая выполняет сейчас только печать.
Строчек кода больше, но зато здесь следование single responsibility principle и каждый из методов можно тестить по отдельности, если б я сделал их публичными.
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
//Это пример, в исходном примере там итератор, потому лучше из этого итератора собрать какой то Collection
Collection<Double> list = Arrays.asList(-100.0, -90.0, -2.0, 0.0, 3.0, 50.0, null);
Stream<Double[]> pairStream = getValueToRefValueStream(list);
processStream(pairStream);
}
private static Stream<Double[]> getValueToRefValueStream(Collection<Double> list) {
Iterator<Double> it = list.iterator();
if (!it.hasNext()) {
return Stream.empty();
}
final AtomicReference<Double> pvRef = new AtomicReference<>(null);
final AtomicReference<Double> cvRef = new AtomicReference<>(it.next());
Stream<Optional<Double[]>> optionalStr = list
.stream()
.skip(1)
.map( (Double plus1) -> {
Double minus1 = pvRef.get();
Double value = cvRef.get();
pvRef.set(cvRef.get());
cvRef.set(plus1);
Double refValue = calculateRefValue(plus1, minus1, value);
if (refValue != null) {
return Optional.of(new Double[]{value, refValue});
}
return Optional.empty();
});
return optionalStr.filter(Optional::isPresent).map(Optional::get);
}
private static Double calculateRefValue(Double plus1, Double minus1, Double value) {
Double result = null;
if (value != null && value != 0) {
if (value < 0) {
result = plus1;
} else if (value > 0) {
result = minus1;
}
}
return result;
}
private static void processStream(Stream<Double[]> pairStream) {
//какие-то операции с value и refValue
pairStream.forEach( a -> {
Double value = a[0];
Double refValue = a[1];
System.out.print(value);
System.out.print(":");
System.out.println(refValue);
});
}
}
PS Больше года не пишу на Java — сейчас Java синтаксис кажется ужас. Для простейших действий до черта строк кода, и велика вероятность ошибиться. Пипец, если из вакансий останется только Java и я не смогу найти работу на нормальных языках, придется на пенсию поход скоро уходить.
E>Строчек кода больше, но зато здесь следование single responsibility principle и каждый из методов можно тестить по отдельности, если б я сделал их публичными.
CS>Double pv, cv;
CS>for (ListIterator<Double> it = list.listIterator(); it.hasNext(); ) {
CS> pv = cv;
CS> cv = it.next();
CS> Double rv;
CS> if (pv != null && cv != 0) {
CS> if (cv < 0)
CS> rv = pv;
CS> else if (cv > 0)
CS> rv = cv;
CS> }
CS> ... //какие-то операции с value и refValue
CS>}
CS>
CS> ... //какие-то операции с value и refValue
А где само value-то? сv? Я так понял по условию refValue всегда != value. Оно или null или prev или next.