JavaRush /Блоги Java /Random-TG /Муқоисакунанда дар Java
Viacheslav
Сатҳи

Муқоисакунанда дар Java

Дар гурӯҳ нашр шудааст
Танҳо одамони танбал дар бораи Comparator ва муқоиса дар Java нанавиштаанд. Ман танбал нестам - бинобар ин ман аз шумо хоҳиш мекунам, ки як варианти дигарро дӯст доред. Умедворам зиёдатӣ нахоҳад буд. Ва ҳа, ин мақола ҷавоб ба савол аст: "Шумо метавонед аз хотира муқоиса кунед?" Умедворам, ки пас аз мутолиаи ин матлаб ҳама метавонанд аз хотира муқоиса бинависанд.
Муқоисакунанда дар Java - 1
Муқаддима Java маълум аст, ки забони ба an object нигаронидашуда мебошад. Дар натиҷа, дар Java кор кардан бо an objectҳо маъмул аст. Аммо дер ё зуд вазифаи му-коисаи an objectхо аз руи ягон принцип ба миён меояд. Ҳамин тавр, дода шудааст: Мо як паём дорем, ки онро синфи Message тавсиф мекунад:
public static class Message {
    private String message;
    private int id;

    public Message(String message) {
        this.message = message;
        this.id = new Random().nextInt(1000);
    }
    public String getMessage() {
        return message;
    }
    public Integer getId() {
        return id;
    }
    public String toString() {
        return "[" + id + "] " + message;
    }
}
Биёед ин синфро ба Tutorialspoint java compiler илова кунем . Биёед илова кардани воридотро низ дар хотир дорем:
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
Дар усули асосӣ мо якчанд паёмҳоро эҷод мекунем:
public static void main(String[] args){
    List<Message> messages = new ArrayList();
    messages.add(new Message("Hello, World!"));
    messages.add(new Message("Hello, Sun!"));
    System.out.println(messages);
}
Биёед дар бораи он фикр кунем, ки агар мо онҳоро муқоиса кардан хоҳем, чӣ кор кунем? Масалан, мо мехоҳем аз рӯи ID ҷудо кунем. Ва барои ба вуҷуд овардани тартиб, шумо бояд бо ягон роҳ an objectҳоро муқоиса кунед, то бифаҳмед, ки кадом an object пештар аст (яъне хурдтар) ва кадомаш дар оянда (яъне калонтар). Биёед бо синф ба монанди java.lang.Object оғоз кунем . Тавре ки мо медонем, ҳама синфҳо ба таври ғайримустақим аз ин синфи Object мерос мегиранд. Ва ин мантиқист, зеро Ин аслан мафҳумро ифода мекунад: "Ҳама чиз an object аст" ва рафтори умумиро барои ҳама синфҳо таъмин мекунад. Ва ин синф муайян мекунад, ки ҳар як синф ду усул дорад: → hashCode Усули hashCode баъзе муаррифии ададӣ (int)-и an objectро ҳамчун намунаи синф бармегардонад. Ин чӣ маъно дорад? Ин маънои онро дорад, ки агар шумо ду мисоли гуногуни синфро эҷод карда бошед, пас азбаски мисолҳо гуногунанд, hashCode онҳо бояд гуногун бошад. Ин аст он чизе, ки дар тавсифи усул гуфта мешавад: "Чӣ қадаре ки оқилона амалӣ бошад, усули hashCode, ки аз ҷониби синфи Object муайян шудааст, ададҳои алоҳидаро барои an objectҳои алоҳида бармегардонад" Яъне, агар ин ду мисоли гуногун бошанд, пас онҳо бояд гуногун дошта бошанд. hashCodes. Яъне ин усул барои муқоисаи мо мувофиқ нест. → баробар Усули баробар ба саволи "an objectҳо баробаранд" ҷавоб медиҳад ва мантиқиро бармегардонад. Ин усул рамзи пешфарз дорад:
public boolean equals(Object obj) {
    return (this == obj);
}
Яъне, бидуни барҳам додани ин усул дар an object, ин усул аслан мегӯяд, ки оё истинодҳо ба an object мувофиқат мекунанд ё не. Ин барои паёмҳои мо мувофиқ нест, зеро мо ба истинодҳо ба an object таваҷҷӯҳ надорем, мо ба ID-и паём таваҷҷӯҳ дорем. Ва ҳатто агар мо усули баробарро бекор кунем, ҳадди аксаре, ки мо мегирем: "Онҳо баробаранд" ё "Онҳо баробар нестанд." Аммо барои муайян кардани тартиб ин барои мо кифоя нест.

Муқоисакунанда ва муқоисашаванда дар Java

Чӣ ба мо мувофиқ аст? Агар дар тарҷумон калимаи “муқоиса”-ро ба забони англисӣ тарҷума кунем, тарҷумаи “муқоиса кардан”-ро мегирем. Аҷоиб, пас ба мо касе лозим аст, ки муқоиса кунад. Агар шумо ин муқоисаро муқоиса кунед, пас касе, ки муқоиса мекунад, Муқоисакунанда аст. Биёед Java Api -ро кушоем ва дар он ҷо Comparator -ро пайдо кунем . Ва дар ҳақиқат, чунин интерфейс вуҷуд дорад - java.util.Comparator java.util.Comparator ва java.lang.Comparable Тавре ки шумо мебинед, чунин интерфейс вуҷуд дорад. Синфест, ки онро амалӣ мекунад, мегӯяд, ки "Ман функсияи муқоисаи an objectҳоро иҷро мекунам." Ягона чизе, ки дар ҳақиқат дар хотир бояд дошт, шартномаи муқоисавӣ мебошад, ки ба таври зерин ифода шудааст:

Comparator возвращает int по следующей схеме: 
  • отрицательный int (первый an object отрицательный, то есть меньше)
  • положительный int (первый an object положительный, хороший, то есть больший)
  • ноль = an objectы равны
Акнун биёед як муқоисаро нависед. Мо бояд java.util.Comparator -ро ворид кунем . Пас аз воридот, ба main усули илова кунед: Comparator<Message> comparator = new Comparator<Message>(); Табиист, ки ин кор намекунад, зеро Comparator интерфейс аст. Аз ин рӯ, пас аз қавс мо ҷингилаҳоро илова мекунем { }. Дар ин қавс мо усулро менависем:
public int compare(Message o1, Message o2) {
    return o1.getId().compareTo(o2.getId());
}
Шумо ҳатто лозим нест, ки ин навиштанро фаромӯш кунед. Муқоисакунанда касест, ки муқоиса мекунад, яъне муқоиса мекунад. Барои ҷавоб додан ба саволе, ки an objectҳои муқоисашуда дар кадом тартиб ҷойгиранд, мо ба int бармегардем. Дар асл, ҳамааш ҳамин аст. Содда ва ба осонӣ. Тавре ки мо аз мисол мебинем, ба ғайр аз Comparator, боз як интерфейси дигар вуҷуд дорад - java.lang.Comparable , ки татбиқи он мо бояд усули compareTo -ро муайян кунем . Ин интерфейс мегӯяд, ки "Кинфе, ки интерфейсро амалӣ мекунад, имкон медиҳад, ки мисолҳои синф муқоиса карда шаванд." Масалан, татбиқи Integer аз муқоисаи муқоиса чунин менамояд:
(x < y) ? -1 : ((x == y) ? 0 : 1)
Чӣ тавр ҳамаи ин интерфейсҳоро дар хотир бояд дошт? Барои чӣ? Ҳама чиз аз забони англисӣ меояд. Муқоиса кардан - муқоиса кардан, муқоисакунанда Муқоисакунанда (ҳамчун бақайдгиранда, масалан. Яъне, он касе, ки сабти ном мекунад) ва сифатҳои "муқоисашуда" Муқоисашаванда аст. Хуб, "Муқоиса бо" на танҳо ҳамчун муқоиса бо, балки ҳамчун муқоиса бо тарҷума тарҷума шудааст. Ин оддӣ аст. Забони ҷавиро афроди инглисзабон навиштаанд ва дар номгузории ҳама чиз дар Java онҳо танҳо забони инглисиро роҳнамоӣ мекарданд ва дар номгузорӣ як навъ мантиқе вуҷуд дошт. Ва усули compareTo тавсиф мекунад, ки чӣ гуна як мисоли синфро бо мисолҳои дигар муқоиса кардан лозим аст. Масалан, сатрҳо аз ҷиҳати лексиграфӣ муқоиса карда мешаванд ва рақамҳо аз рӯи арзиш муқоиса карда мешаванд.
Муқоисакунанда дар Java - 2
Java 8 баъзе тағйироти хуб овард. Агар мо ба интерфейси Comparator бодиққат назар кунем, мо мебинем, ки дар болои он эзоҳ мавҷуд аст @FunctionalInterface. Дар асл, ин эзоҳ барои маълумот аст ва маънои онро дорад, ки ин интерфейс функсионалӣ аст. Ин маънои онро дорад, ки ин интерфейс танҳо 1 усули абстрактӣ бидуни татбиқ дорад. Ин ба мо чӣ медиҳад? Мо метавонем рамзи муқоисакунандаро ҳоло чунин нависем:
Comparator<Message> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
Дар қавс нишон дода шудааст, ки мо тағирёбандаҳоро чӣ гуна ном мебарем. Худи Java инро хоҳад дид, зеро ... Агар танҳо як усул вуҷуд дошта бошад, пас маълум мешавад, ки кадом параметрҳои воридотӣ, чанд ва кадом намудҳо лозиманд. Баъдан, мо бо тирча мегӯем, ки мо мехоҳем онҳоро ба ин қисмати code интиқол диҳем. Илова бар ин, ба шарофати Java 8, усулҳои пешфарз дар интерфейсҳо пайдо шуданд - ин усулҳое мебошанд, ки ҳангоми татбиқи интерфейс ба таври нобаёнӣ (бо нобаёнӣ) пайдо мешаванд. Якчанд инҳо дар интерфейси Comparator мавҷуданд. Масалан:
Comparator moreImportant = Comparator.reverseOrder();
Comparator lessImportant = Comparator.naturalOrder();
Як усули дигаре ҳаст, ки рамзи шуморо тозатар мекунад. Биёед мисоли болоро бубинем, ки дар он муқоисакунандаи худро тавсиф кардем. Ӯ чӣ кор мекунад? Ин хеле примитивист. Он танҳо an objectро мегирад ва аз он арзиши муқоисашавандаро мегирад. Масалан, Integer муқоисашавандаро амалӣ мекунад, аз ин рӯ мо тавонистем муқоисаро дар арзишҳои ID паём иҷро кунем. Ин функсияи муқоисакунандаи оддиро низ чунин навиштан мумкин аст:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
Яъне, айнан, "Мо як Муқоисакунанда дорем, ки чунин муқоиса мекунад: он an objectҳоро мегирад, бо истифода аз усули getId() аз онҳо Муқоисашаванда мегирад, бо истифода аз compareTo муқоиса мекунад." Ва дигар тарҳҳои даҳшатнок нест. Ва дар охир боз як хусусиятро кайд кардан мехохам. Муқоисаҳоро метавон бо ҳам занҷирбанд кард. Барои намуна:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
comparator = comparator.thenComparing(obj -> obj.getMessage().length());

Ариза

Эъломияи муқоисавӣ комилан мантиқӣ баромад, ҳамин тавр не? Акнун мо бояд бубинем, ки онро чӣ гуна ва дар кадом ҷойҳо истифода барем. → Collections.sort (java.util.Collections) Албатта, мо метавонем коллексияҳоро ҳамин тавр ҷудо кунем. Аммо на ҳама чиз, танҳо рӯйхатҳо. Ва дар ин ҷо ягон чизи ғайриоддӣ нест, зеро ... Ин рӯйхатест, ки дастрасӣ ба унсурро аз рӯи индекс талаб мекунад. Ва ин имкон медиҳад, ки элементи рақами дуюм бо унсури рақами се иваз карда шавад. Аз ин рӯ, мураттабсозӣ бо ин роҳ танҳо барои рӯйхатҳо имконпазир аст:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
Collections.sort(messages, comparator);
Arrays.sort (java.util.Arrays) Массивҳо инчунин барои ҷудокунӣ қулай мебошанд. Боз, бо ҳамон сабаби дастрасии унсурҳо аз рӯи индекс. → Насли java.util.SortedSet ва java.util.SortedMap Тавре ки мо дар ёд дорем, Set ва Map тартиби нигоҳдории сабтҳоро кафолат намедиҳад. АММО мо амалияҳои махсус дорем, ки тартиботро кафолат медиҳанд. Ва агар унсурҳои коллексия java.lang.Comparable-ро амалӣ накунанд, пас мо метавонем Comparator-ро ба созандаи чунин коллексияҳо гузорем:
Set<Message> msgSet = new TreeSet(comparator);
Stream API Дар Stream Api, ки дар Java 8 пайдо шудааст, муқоисакунанда ба шумо имкон медиҳад, ки корро дар унсурҳои ҷараён содда кунед. Масалан, ба мо як пайдарпаии рақамҳои тасодуфӣ аз 0 то 999 лозим аст:
Supplier<Integer> randomizer = () -> new Random().nextInt(1000);
Stream.generate(randomizer)
    .limit(10)
    .sorted(Comparator.naturalOrder())
    .forEach(e -> System.out.println(e));
Мо метавонистем бас кунем, аммо мушкилоти ҷолибтаре ҳастанд. Масалан, ба шумо лозим аст, ки Харитаеро омода кунед, ки дар он калиди ID-и паём аст. Дар айни замон, мо мехоҳем ин калидҳоро тавре ҷудо кунем, ки калидҳо аз хурдтарин ба калонтар ба тартиб дароянд. Биёед бо ин code оғоз кунем:
Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg));
Он чизе ки мо ба ин ҷо бармегардем, воқеан як HashMap аст. Ва чунон ки мо медонем, он ягон фармоишро кафолат намедиҳад. Аз ин рӯ, сабтҳои мо, ки аз рӯи ID ҷудо карда шудаанд, танҳо аз кор баромаданд. Нағз не. Мо бояд коллекторамонро каме иваз кунем:
Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg, (oldValue, newValue) -> oldValue, TreeMap::new));
Рамз каме ғазабтар ба назар мерасид, аммо ҳоло мушкилот ба туфайли татбиқи возеҳи TreeMap дуруст ҳал карда шуд. Шумо метавонед бештар дар бораи гурӯҳҳои гуногун дар ин ҷо бихонед: Шумо метавонед коллекторро худатон созед. Шумо метавонед маълумоти бештарро дар ин ҷо хонед: "Сохтани коллектори фармоишӣ дар Java 8" . Ва дар ин ҷо хондани муҳокима муфид аст: "Рӯйхати Java 8 барои харита бо ҷараён" .
Муқоисакунанда дар Java - 3
Рақаҳои муқоисавӣ ва муқоисашаванда хубанд. Аммо як нозуки бо онҳо алоқаманд аст, ки ба ёдоварист. Вақте ки синф ҷудокуниро иҷро мекунад, он ҳисоб мекунад, ки он метавонад синфи шуморо ба муқоисашаванда гузорад. Агар ин тавр набошад, шумо дар вақти иҷро хатогӣ хоҳед гирифт. Биёед як мисолро дида бароем:
SortedSet<Message> msg = new TreeSet<>();
msg.add(new Message(2, "Developer".getBytes()));
Чунин ба назар мерасад, ки дар ин ҷо ҳеҷ бадӣ нест. Аммо дар асл, дар мисоли мо, он бо хатогӣ дучор мешавад: java.lang.ClassCastException: Message cannot be cast to java.lang.Comparable Ва ҳама аз он сабаб, ки он кӯшиш кард, ки унсурҳоро ҷудо кунад (Дар ниҳоят, ин SortedSet аст). Ва ман натавонистам. Шумо бояд инро ҳангоми кор бо SortedMap ва SortedSet дар хотир доред. Ба таври иловагӣ барои тамошо тавсия дода мешавад: Юрий Ткач: HashSet ва TreeSet - Коллексияҳо №1 - Java Advanced
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION