LINUX.ORG.RU

[Sugar for coffie]Сахарок для java


0

2

Небольшой совет как писать меньше кода в убогом недоязычке java, при инициализации убогих массивов, хешмапов и прочей шелупони.


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Этакая штука для создания карт, массивов и т.п. одной строкой
 * <p/>
 * @author wfrr
 */
public final class Sugar {
  
  /**
   * Создает объект типа {@link Pair }
   * @param <L>
   * @param <R>
   * @param l
   * @param r
   * @return 
   */
  public static <L, R> Pair<L, R> p(L l, R r) {
    return new Pair<L, R>(l, r);
  }
  
  /**
   * Создает карту из переданных пар
   * @param <K>
   * @param <V>
   * @param pairs
   * @return 
   */
  public static <K, V> Map<K, V> map(Pair<K, V> ... pairs) {
    HashMap<K, V> m = new HashMap<K, V>();
    if(pairs != null) {
      for(Pair<K, V> pair: pairs) {
        m.put(pair.getLeft(), pair.getRight());
      }
    }
    return m;
  }
  
  /**
   * Возвращает массив переданных элементов
   * @param <T>
   * @param ts
   * @return 
   */
  public static <T> T[] array(T ... ts) {
    return ts;
  }
  
  /**
   * Заполняет коллекцию
   * @param <T>
   * @param ts
   * @return 
   */
  public static<C extends Collection<T>, T> C fill(C c, T ... ts) {
    if(ts != null) {
      for(T t: ts) {
        c.add(t);
      }
    }
    return c;
  }
  
  /**
   * Возвращает мутабельный список содержащий переданные элементы
   * @param <T>
   * @param ts
   * @return 
   */
  public static <T> List<T> list(T ... ts) {
    if(ts == null) {
      return new ArrayList<T>();
    }
    return fill(new ArrayList<T>(ts.length), ts);
  }
  
  /**
   * Возвращает мутабельный набор содеражащий переданные элементы
   * @param <T>
   * @param ts
   * @return 
   */
  public static <T> Set<T> set(T ... ts) {
    if(ts == null) {
      return new HashSet<T>();
    }
    return fill(new HashSet<T>(ts.length), ts);
  }
}

/**
 * Пара, для различный контейнеров и прочего. 
 * @author wfrr
 */
public class Pair<T1, T2> {
  T1 left;
  T2 right;

  public Pair() {
  }

  public Pair(T1 left, T2 right) {
    this.left = left;
    this.right = right;
  }

  public T1 getLeft() {
    return left;
  }

  public void setLeft(T1 left) {
    this.left = left;
  }

  public T2 getRight() {
    return right;
  }

  public void setRight(T2 right) {
    this.right = right;
  }

  @Override
  @SuppressWarnings("unchecked")
  public boolean equals(Object obj) {
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    final Pair<T1, T2> other =
      (Pair<T1, T2>) obj;
    if (this.left != other.left &&
      (this.left == null || !this.left.equals(other.left))) {
      return false;
    }
    if (this.right != other.right && (this.right == null ||
      !this.right.equals(other.right))) {
      return false;
    }
    return true;
  }

  @Override
  public int hashCode() {
    int hash = 5;
    hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0);
    hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0);
    return hash;
  }

  @Override
  public String toString() {
    return "(" + left + ", " + right + ")";
  }
}

Юзать так:

Map<String, Integer> m = map(p("three",3),p("two",2))
★★☆

Нормально.

Только класс Pair реализовал так себе, лучше immutable. Методе list - лишний, потому как в жаве и так есть Arrays.asList(). Интерфейс Collectons лучше не используй - не соответсвует принципу лисков. В методе set - на null лучше IllegalArgumentException кинуть.

Раньше тоже примерно такие хелперы писал. Потом мне показали Google Collections - там все это из каробки + поддержка нормальных немутабельных коллекций, в т.ч. с билдерами.

dizza ★★★★★
()

Годная идея. Спасибо.

urxvt ★★★★★
()

фига простыня. Бедные жабапрограммисты :)

Zubchick
()

> Небольшой совет как писать меньше кода в убогом недоязычке java, при инициализации убогих массивов, хешмапов и прочей шелупони.

better not to write in this crappy language at all.

anonymous
()

> Небольшой совет как писать меньше кода в убогом недоязычке java
Не лопни.

Не вижу ничего полезного в выше приведенном коде. Открой для себя Arrays.asList.

Замена Pair<Integer,String> a = new Pair<Integer,String>(1, «2») на Pair<Integer,String> a = Sugar.Pair(1, «2»).
Замена a = new Integer[] {1, 2, 3, 4} на а = Sugar.array(1, 2, 3, 4)

и тд, не делают код читабельнее.

Необходимость конструкция вида
Map<String, Integer> m = map(p(«three»,3),p(«two»,2)
следствие плохого проектирования кода, имхо

FollowTheRabbit
()

К слову, когда мне нужно было вернуть пустой List, то использовать Collections.emptyList(). Насколько понимаю, это несколько лучше чем каждый раз делать new, так как создаётся меньше объектов.

php-coder ★★★★★
()
Ответ на: комментарий от FollowTheRabbit

и тд, не делают код читабельнее.

Делают. Любое устранение ненужного, очевидного кода, делает код в целом более читабельным. Вот так:

var xs = asList(1, 2, 3, 4);

Было бы еще лучше.

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

Согласен, профессор, - такого слова нет...На сколько мне не изменяет память, даже в голландском языке =)

Также не ясно зачем ТС пример комментировал в жабадок-стиле. Однострочных бы хватило...

И всё это понты....для жжшечки

m4n71k0r
()

Вот это убожество.

anonymous
()

Я бы такой код не принял.

Кстати, русский в комментариях - моветон

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

Только класс Pair реализовал так себе, лучше immutable.

Это да, но в данном случае он наружу не высовывается, а задумывался восе для другого. Но если писать изначально то ты прав.

В методе set - на null лучше IllegalArgumentException кинуть.

Не, тут задача не побольше гимора создать, а избавится от дубляжа, в основном для тестов - т.е. инициализация HashSet в три буквы.

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

Потом мне показали Google Collections - там все это из каробки + поддержка нормальных немутабельных коллекций, в т.ч. с билдерами.

в большем проекте столько зависимостей, что даже с ivy возникает нетривиальный гимор и тормоза при сборке, так что ради такой мелочи можно повелосипедствовать

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

так что ради такой мелочи можно повелосипедствовать

Хм странно. Может я не знаю что у вас там. Но я вот использую мавен и никакого геморо и тормозов не замечаю... JODA Time и Google Collections можно прям сразу подключають к любому проекту.

Кстати, гугл колекшионсы сейчем входят в состав Guava - вот это реально крутая штука. Жду релиза с нетерпением.

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

ога, 10 экземпляров commons-collection и log4j я в одном чудо проекте маськовской фирмы видел, они тоже мавен юзают

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

10 экземпляров commons-collection и log4j

Это как у них такое получилось? И вообще они походу mvn dependency:analyze / tree не осилили. ССЗБ в общем.

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

в общем нужно разрабатывать, а не тратить недели на совокупление чужих зависимостей из-за одного класса.

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

Совокупление у меня было лишь однажды из-за log4j. В общем странно все это. Я на мавен сам долго скептически смотрел. Потом на работе как-то заставили и меня поперло.

dizza ★★★★★
()

Некоторые вещи из этого есть в google collections library.

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

Делают. Любое устранение ненужного, очевидного кода, делает код в целом более читабельным. Вот так:

По-моему код

a = new Integer[] {1, 2, 3, 4};
вполне очевиден, и каждый символ в нём осмысленнен и нужен.

а

а = Sugar.array(1, 2, 3, 4) 
обязательно потребует изучения исходного кода метода array, мало ли что там белка могла придумать. И не даёт в общем то никакого реального профита.

Вот что реально помогает, это делать фактори методы вместо конструкторов, вроде

class MyGenericClass<T> {
    MyGenericClass(T arg) { ... }
    public static MyGenericClass<T> create(T arg) { return new MyGenericClass<T>(arg); }
}
, поскольку позволяет убрать дублирование кода. Правда выглядит очень неконсистентно, но выгоды перевешивают недостатки. В принципе вроде обещали в следующей джаве это улучшить, так что костыли будут не нужны.

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

обязательно потребует изучения исходного кода метода array, мало ли что там белка могла придумать. И не даёт в общем то никакого реального профита.

Бедненький, ты наверняка весь код jdk и всех используемых библитек наизусть выучил, мало ли что там могли придумать?

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

Коду JDK больше доверия :) И таки да, почти весь частоиспользуемый код в JDK я когда то просматривал. Только JDK одна на весь мир, а в каждом проекте найдётся своя белка :) Так что я за то, чтобы такой метод был в JDK, но против того, чтобы в каждом проекте из Java делали свой суперязык.

Legioner ★★★★★
()

сыро.

Pair не нужен сам по себе, его .equals() спорен (имхо надо его сделать final-классом). Остальное есть в java.util.Collections, java.util.Arrays и в Google Collections

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

ага только любители мавена при малейшей потребности в функционале юзают ant (ага, две системы сборки разом, энтерпрайзно!), а ivy - расширение к ant, и гораздо более функциональное чем убогий maven с его убогими дескрипторами.

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

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

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

Collections.emptyList() немутабельный и возвращает константу Collections.EMPTY_LIST, только с преобразованием к заказанному генерику

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

ant плодит бардак, особенно когда много модулей в проекте и они делаются разными разработчиками. Maven дает хоть какую-то определенность + помогает импортировать проект в IDE

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

Так делаю только те, кто не осилил maven. Каюсь аж целый один раз юзал maven ant plugin, но потом после доведения кода до ума отпала потребность и в нем.

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

Блин, а методы-утилиты возвращают мутабельные, потому логично что пустой они вернут также мутабельный.

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

обязательно потребует изучения исходного кода метода array, мало ли что там белка могла придумать

Открыть метод - этож пипец как долго. А прочитать целую строчку кода это ваще нириально. Да. И ничего, что свое ненормальное любопытство нужно удовлетворить всего один раз.

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

в проекте у нас около десятка модулей, это много?

и емнип все ide умеют импортировать ant проекты

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

а соблюдение контрактов? Или это прикол такой - если аргумент есть то коллекция мутабельна, а нету - значит немутабельна. Прикольно с моей точки зрения.

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

каждый проект на ant уникален по своей организации, maven позволяет не тратя время открыть чужой проект и поковыряться в нем. Вот недавний пример - надо было зафиксить одну мелочь в lucene+solr, убил наверное часа полтора затягивая проект в IDEA. Был бы он на maven, не пришлось бы

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

ну а какие там контракты? Например Collections.singletonList тоже immutable. А вот Collections.checkedList - mutable, что тоже логично

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

Нормальные имена нужно методам давать. Вот тебе примеры из GC:

List<Integer> ints = Lists.newArrayList(1, 2, 3);
		
List<Integer> intsi = ImmutableList.of(1, 2, 3);
		
ImmutableList.Builder<Integer> ib = ImmutableList.builder();
ib.add(1);
ib.add(2);
ib.add(3);
List<Integer> intsi2 = ib.build();
dizza ★★★★★
()
Ответ на: комментарий от maxcom

ну а какие там контракты?

В данном случае аналогично как Collections.checkedList - mutable, а при передаче ему пустой коллекции immutable, не находишь что странное поведение?

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

Впрочем, если я использую immutable список, то обычно так:

Iterable<Integer> ints = Lists.newArrayList(1, 2, 3);

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

Нормальные имена нужно методам давать.

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

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

хотя не повторю:

List<String> s = list("a","b");
s.add("c"); //ok! все мутабельно

List<String> s = list();
s.add("c"); //fail! иммутабельно!!???

теперь точно все.

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

Ну если для сокращения имен, то можно примерно вот так:

public class Utils {
	
	public static <T> List<T> mlist(T... xs) {
		return Lists.newArrayList(xs);
	}
	
	public static <T> List<T> list(T... xs) {
		return ImmutableList.of(xs);
	}
}
dizza ★★★★★
()
Ответ на: комментарий от anonymous

это да 8) но увы и ах, иде для скалы нету рабочих

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