Показаны сообщения с ярлыком полезнознание. Показать все сообщения
Показаны сообщения с ярлыком полезнознание. Показать все сообщения

воскресенье, 14 февраля 2010 г.

Comparable & Comparator

Сегодня мы поговорим о сравнениях. Они нужны в первую очередь, для сортировки.
Например в доменной модели есть User (POJO))

public class User {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}

И мы на сайте выводим их в алфавитном порядке.
Как же их отсортировать-то?
Можно создать массив, поместить туда пользователей и написав сортировку пузырьком отсортировать их.
Что же делать, если писать сортировку нет охоты? Можно воспользоваться стандартными средствами.
class UserService{
static List users;
static List getUsers(){
return users;
}
}

class SomeController{
void foo(){
Collections.sort(UserService.getUsers());
}
}

Но как же компьютер отсортирует пользователей, как он узнает критерии сравнения? Надо ему о них рассказать.
Для этого изменим класс User
public class User implements Comparable<User>{
private String name;
private int age;
//...
@Override
public int compareTo(User o) {
return name.compareTo(o.name);
}
}

compareTo() возвращает отрицательное число если текущий объект должен идти раньше, чем тот с чем сравнивают.

Все хорошо проект сделан. Но вот не задача, пришел заказчик и хочет, дабы мы еще сделали сортировку по возрасту. А не послать ли нам его? – хорошая идея, но, скорее всего, придется таки делать.
Для этого есть механизм “сравнителей”.
Например,
class CompareByAge implements Comparator<User>{
@Override
public int compare(User u1, User u2) {
return u1.getAge() - u2.getAge();
}
}

Сортировка с его использованием будет выглядеть как
 void bar(){
Collections.sort(UserService.getUsers(), new CompareByAge());
}

Преимущество такого подхода в том, что может существовать сколь угодно компараторов.
Отметим, даты, строки и многих другие класс реализуют интерфейс Comparable, поэтому мы можем сортировать их без дополнительных сложностей.

Пробуйте!

(Статья подготовлена совместно compiler & Link)

TreeSet

На лекции у меня не получилось продемонстрировать возможности TreeSet и я сказал что он особо не используется, по вчера у меня возникла ситуация когда логично объекты нужно хранить в отсортированном порядке, первой мыслю было использовать List и сортировать его, но на каком этапе это делать? На помощь мне пришел TreeSet.

Итак, как же им пользоваться?
Напишем элементарный пример

public class MyClass implements Comparable {
    String str;
    public MyClass(String str) {
        this.str = str;
    }
    @Override
    public int compareTo(MyClass o) {
        return str.compareTo(o.str);
    }
    public static void main(String[] args) {
        Set ss = new TreeSet();
        ss.add(new MyClass("a"));
        ss.add(new MyClass("e"));
        ss.add(new MyClass("g"));
        ss.add(new MyClass("b"));
        ss.add(new MyClass("c"));
        for(MyClass s : ss){
            System.out.println(s.str);
        }
    }
}

Теперь объясню все это.

TreeSet работает вполне логично, туда добавляются классы и она их хранит в отсортированном порядке, нюанс тут в том, что для нужного нам порядка сортировки нежно реализовать интерфейс Comparable, или передать в конструктор класс, реализующий интерфейс Comparator, о них я напишу сегодня позже.

RegExp

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

Регулярные выражения это, так сказать, шаблон текста. Они используются для проверки данных веденных пользователем, автоматизации получения информации из текстового документа и других случаях обработки текста.

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

Рассмотрим базовый синтаксис
x — символ x
\0n — символ с восьмеричным кодом n
\xh — символ с шестнадцатеричным кодом n
. — любая буква
[abc] — любая из букв abc
[a-z] — любая из букв от a до z (все маленькие буквы латиницы)
[^abc] — все символы кроме abc
^ — начало текста
$ — конец текста
\ — экранирующий символ (например знак точки будет "\.")
() — группировка символов (в дальнейшем рассмотрим еще одно очень хорошее их свойство)

\t — табуляция
\n — знак переноса строки
\r — знак возврата
\b — граница слова
\d — цифры
\D — не цифры
\s — пустое пространство (пробел, табуляция, etc)
\S — не пустое пространство
\w — символ слова ([a—zA—Z_0—9])
\W — не символ слова

Квантификаторы:
X? — X, 0 или 1
X* — X, 0 и больше раз
X+ — X, 1 и больше раз
X{n} — X, n раз
X{n,} — X, n и больше раз
X{n,m} — X, от n до m раз

| — логическое или

Я привел не все, и так я думаю у вас возникла мысль "куда я попал".

Рассмотрим элементарный пример: нам нужно проверить правильность введенного e—mail адреса, какие у нас требования:
— начинается с буквы
— может содержать цифры, буквы, знаки —_. в любом количестве
— дальше должна идти @
— домен может содержать буквы и цифры
— потом . и 2 или 3 буквы домена 1—го уровня

распишем выражение по частям
[a-z] — начинается с буквы
[a-z0-9\-_.]* — может содержать цифры, буквы, знаки —_.
@ — дальше должна идти @
[a-z0-9] — домен может содержать буквы и цифры
\.[a-z]{2,3} — потом . и 2 или 3 буквы домена 1—го уровня

Что в итоге получилось:
[a-z][a-z0-9\-_.]*@[a-z0-9]\.[a-z]{2,3}
Вот такая страшная штука, но не бойтесь, при реальном использовании все намного страшнее.

Нужно заметить что перед проверкой нужно привести строку к нижнему регистру.

суббота, 13 февраля 2010 г.

Короткие слова и комбинации клавиш в eclipse

Полезные из коротких слов: syso, main.
А комбинации можно посмотреть ctrl+shift+l или в настройках.
Самые полезные из них:
с+s+o(организовать импорт)
с+space(дополнить слово, очень мощная штука, пользуюсь почти в каждой строчке)
s+a+s(создать метод, лучше самому посмотреть)
с+s+t(перейти к классу)
Ну и стандортные(сtrl+s итд).

Еще вспомню - допишу.

Да, точно, вот мне напомнили:
полезная комбинация с+/ комментит строки(java), в IDEA можно было комментировать так любой код, но в eclipse такого увы нет.

Еще полезно: ctrl+d удаляет строку.

Форматирование чисел

При написании программ для работы с дробными чистами часть возникает проблема их красивого вывода, для этого примиряется класс NumberFormatter, который в качестве конструктора принимает экземпляр класса NumberFormat.

Пример:

double pi = Math.PI;
NumberFormat format = NumberFormat.getNumberInstance();
format.setMaximumFractionDigits(4);
NumberFormatter formatter = new NumberFormatter(format);
try {
 System.out.println(formatter.valueToString(pi));
} catch (ParseException e) {
 e.printStackTrace();
}

Данная программа выведет 3,1416, то есть округлит число.

NumberFormat.getNumberInstance() - форматирование чисел
NumberFormat.getCurrencyInstance() - форматирование денег
NumberFormat.getPercentInstance() - форматирование как проценты(1 = 100%)

пятница, 12 февраля 2010 г.

Разделяй и властвуй

Полезные функции:
У String есть метод split(), который принимает разделитель(регулярное выражение, которым я планирую посветить целую лекцию). Эта функция делит строку по этому разделителю и возвращает массив строк, может не очень понятно, объясню на примере

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

Пример:
"суп каша, борщ,макароны картошка".split("[ ,]+")
вернет массив названий всех блюд, удобно, не правда ли?

P.S. Возможно я кого-то напугал регулярными выражениями, разделять можно по обычной строке, например "суп каша борщ макароны картошка".split(" ");