English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Detaillierte Analyse des Vergleichsproblems in Java

Das Vergleichsproblem in Java ist ein sehr grundlegendes und leicht verwirrendes Problem. Heute werden einige Punkte, die leicht falsch verstanden werden können, detailliert zusammengefasst und aufbereitet, hoffentlich nützt es allen bei der Lern- und Interviewvorbereitung.

Ein, der Unterschied zwischen == und equals()

Zunächst müssen wir den Unterschied zwischen == und equals() kennen, == vergleicht immer die Adresswerte, für grundlegende Datentypen ist der ==-Vergleich tatsächlich der Vergleich der Variablenwerte, und für Referenzdatentypen wird der Adresswert verglichen. Hier ist besonders darauf zu achten, dass der String-Typ leicht fälschlicherweise mit == verwendet wird und leicht Fehler verursachen kann. Die equals()-Methode ist eine Methode in der Object-Klasse, wir wissen, dass alle Klassen in Java standardmäßig die Object-Klasse vererben, daher haben alle Objekte die equals()-Methode. Wie die equals()-Methode in der Object-Klasse gezeigt wird:

Wie aus dem Quellcode hervorgeht, verwendet die equals()-Methode in der Object-Klasse auch == als Grundlage, daher wird tatsächlich der Adresswert verglichen. Daher müssen wir die equals()-Methode überschreiben, wenn wir die equals()-Methode für andere Vergleiche verwenden möchten.

Zwei, die grundlegenden Datentypen und ihre Wrapper-Klassen

Wir alle wissen, dass byte, short, int, long, boolean, char, double, float diese acht die grundlegenden Datentypen sind, die deklarierten Variablen werden im Stapel Speicher gespeichert. Und die entsprechenden Wrapper-Typen (Byte, Short, Integer, Long, Boolean, Character, Double) definierten Variablen existieren im Heap-Speicher. Für die grundlegenden Datentypen sind ihre Vergleiche relativ einfach, d.h. ob sie gleich sind, mit == zu beurteilen, und um die Größe zu vergleichen, mit <, >, <=, >= auszureichen. Für die Wrapper-Typen ist es jedoch etwas anders.

Zunächst, um zu prüfen, ob sie gleich sind, schauen wir uns das Ausgaberesultat des folgenden Codes an:

package dailytest;
import org.junit.Test;
/**
 * Java中的比较总结
 * @author yrr
 */
public class JavaCompareTest {
  /**
   * Integer-Typen, um zu prüfen, ob sie gleich sind
   */
  @Test
  public void test01() {
    int n3 = 48;
    System.out.println("--------Bei der Verwendung von new-Objekten, wenn der Wert im Intervall [-127,128] liegt---------");
    Integer n7 = new Integer(48);
    Integer n8 = new Integer(48);
    System.out.println(n7 == n8);  //false
    System.out.println(n7 == n3);  //true
    System.out.println("--------Bei der direkten Zuweisungsmethode, wenn der Wert im Intervall [-128,127] liegt---------");
    Integer n1 = 48;
    Integer n2 = 48;
    System.out.println(n3 == n1); //true
    System.out.println(n1 == n2); //true
    System.out.println(n1.equals(n2)); //true
    System.out.println(n1.equals(n3)); //true
    System.out.println(n1== n2); //true
    System.out.println("--------Bei der direkten Zuweisungsmethode, wenn der Wert nicht im Intervall [-127,128] liegt---------");
    Integer n4 = 128;
    Integer n5 = 128;
    int n6 = 128;
    System.out.println(n4 == n5);  //false
    System.out.println(n4 == n6);  //true
    System.out.println(n4.equals(n5)); //true
    System.out.println(n4.equals(n6)); //true
    System.out.println(n4== n5); //true
    //Bei der Verwendung der Methode Integer.intValue() muss darauf geachtet werden, dass sie nicht null ist, um NullPointException zu vermeiden
  }
  /**
   * Long-Typen, um zu prüfen, ob sie gleich sind
   */
  @Test
  public void test02() {
    //Hier ist zu beachten, dass bei der Definition mit long L oder l nicht hinzugefügt werden muss, während bei der Verwendung von Long es obligatorisch ist, sonst wird ein Fehler ausgegeben
    //Die Konstruktion sollte hinzugefügt werden, um den Unterschied zu kennzeichnen
    long n3 = 48L;
    System.out.println("--------Bei der Verwendung von new-Objekten, wenn der Wert im Intervall [-127,128] liegt---------");
    Long n7 = new Long(48);
    Long n8 = new Long(48);
    System.out.println(n7 == n8);  //false
    System.out.println(n7 == n3);  //true
    System.out.println("--------Bei der direkten Zuweisungsmethode, wenn der Wert im Intervall [-127,128] liegt---------");
    Long n1 = 48L;
    Long n2 = 48L;
    System.out.println(n3 == n1); //true
    System.out.println(n1 == n2); //true
    System.out.println(n1.equals(n2)); //true
    System.out.println(n1.equals(n3)); //true
    System.out.println(n1== n2); //true
    System.out.println("--------Bei der direkten Zuweisungsmethode, wenn der Wert nicht im Intervall [-127,128] liegt---------");
    Long n4 = 128L;
    Long n5 = 128L;
    long n6 = 128;
    System.out.println(n4 == n5);  //false
    System.out.println(n4 == n6);  //true
    System.out.println(n4.equals(n5)); //true
    System.out.println(n4.equals(n6)); //true
    System.out.println(n4== n5); //true
    //Bei der Verwendung der Methode Long.intValue() muss darauf geachtet werden, dass sie nicht null ist, um NullPointException zu vermeiden  
  }
}

Für das obige Ausgaberesultat ist folgendes zu beachten:

Zunächst, für die Methode new, um ein Integer- oder Long-Objekt zu deklarieren, da neue Objekte immer im Heap ein Stück Platz beanspruchen, daher wird für == der Speicherort verglichen, was zu false führt. Für die Wrapper-Klassen der Basistypen werden die equals()-Methode überschrieben, um die Größen der Werte zu vergleichen, daher kann mit equals() nach der Größe der Werte entschieden werden. Beim Vergleich von Integer-Variable mit int-Variable wird festgestellt, dass der Vergleich basiert auf der Größe der Werte, da der Integer-Typ bei der Vergleichsoperation automatisch entpackt wird und in den Typ int umgewandelt wird. Diese Erklärung gilt für alle Wrapper-Typen Für die direkte Zuweisungsmethode beträgt der Wert48zwei Integer-Variable, mit == wird true zurückgegeben, wenn der Wert128wird, ist jedoch falsch. Dies liegt daran, dass in der Tiefe für die beiden Integer-Variable n1 = 48; Diese direkte Zuweisung ruft in der Tat die Methode Integer.value() auf. Wir können einfach einen Blick auf den Quellcode der Methode Integer.value() werfen, wie im folgenden Bild gezeigt:

Wir können sehen, dass hier ein if-Abfrage vorliegt, wenn der gegebene i im Intervall [-128,127]] im Bereich zurückgegeben. Daher werden für Werte in diesem Bereich die Adresswerte des Arrays IntegerCache zurückgegeben. Daher wird für Werte in diesem Bereich mit dem ==-Operator true zurückgegeben, während für Werte außerhalb dieses Bereichs neue Objekte erstellt werden, daher wird false zurückgegeben. Dieses Ergebnis gilt auch für die Typen Byte, Short, Integer, Long (interessierte können die Quellcodes der entsprechenden value()-Methoden überprüfen), da der Bereich des Bytes-Typs ist [}}-128,127] 

Für Größenvergleiche ist die Verwendung von >, <, <=, >= problemlos, sie führen zur automatischen Entpackung. Wir empfehlen jedoch, die folgenden beiden Methoden zur Größenvergleiche zu verwenden:

Verwenden Sie die Methode xxxValue(), um in den grundlegenden Datentypen umzuwandeln und zu vergleichen. Verwenden Sie die compareTo()-Methode zum Vergleichen. In den Wrapper-Klassen wird die compareTo()-Methode überschrieben. Durch das Durchsuchen des compareTo()-Quellcodes kann man erkennen, dass es letztlich auch durch die automatische Entpackung in den entsprechenden grundlegenden Datentypen umgewandelt und verglichen wird.

Zwei. Vergleich von Java-Objekten

Nach der obigen Einführung wird der Vergleich von Objekten einfacher. Der Prinzip ist derselbe.

1. Vergleich des String-Typs

Es ist zu beachten, dass der String-Typ nicht direkt mit >, <=, >=, < verwendet werden kann, da sonst ein Kompilationsfehler auftritt.

package dailytest;
import org.junit.Test;
/**
 * Java中的比较总结
 * @author yrr
 */
public class JavaCompareTest {
  @Test
  public void test03() {
    String s1 = new String("123");
    String s2 = new String("123");
    System.out.println(s1 == s2);  //false
    System.out.println(s1.equals(s2));
    String s3 = "234";
    String s4 = "234";
    System.out.println(s3 == s4);  //true
    System.out.println(s3.equals(s4));  //true
    //System.out.println(s1 <= s3); //Der Operator < ist für die Argumenttypen java.lang.String, java.lang.String nicht definiert
    System.out.println(s1.compareTo(s3) < 0);  //true
  }
}

 2. Vergleich von Klassenobjekten

Die Schlussfolgerung der Klassenobjektvergleiche ist ebenfalls die gleiche, aber im Vergleich zu grundlegenden Datentypen und String-Typen etwas komplexer.

Um zu bestimmen, ob zwei Objekte nach bestimmten Regeln gleich sind, muss die Methode equals() in der zu überprüfenden Klasse überschrieben werden. Ein Beispielcode ist wie folgt:

package dailytest;
import org.junit.Test;
/**
 * Java中的比较总结
 * @author yrr
 */
public class JavaCompareTest {
  @Test
  public void test04() {
    Person p1 = new Person("yrr",18);
    Person p2 = new Person("yrr",18);
    System.out.println(p1 == p2);  //false
    System.out.println(p2.equals(p1)); //true
  }
}
class Person{
  private String name;  
  private Integer age;
  public Person() {
  }
  public Person(String name, Integer age) {
    this.name = name;
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public Integer getAge() {
    return age;
  }
  @Override
  public boolean equals(Object obj) {
    Person person = (Person) obj;
    return name.equals(person.getName()) && age.equals(person.getAge());
  }
}

而如果要比较两个对象的大小(这也是常会问到的面试题),有两种方式:

被比较类实现Comparable接口,并重写compareTo()方法 自定义实现了一个Comparator接口的类或者利用内部类,重写compare()方法 两者的区别:前者定义在被比较类上,而后者定义在被比较类外。通过这种区别,两者的优缺点也很明显,前者简单,但需要对被比较类进行修改,而后者则不需要修改原代码,更加灵活。

第一种方式,示例代码如下:

package dailytest;
import org.junit.Test;
/**
 * Java中的比较总结
 * @author yrr
 */
public class JavaCompareTest {
  @Test
  public void test5() {
    Person p1 = new Person("yrr",18);
    Person p2 = new Person("wx",19);
    System.out.println(p1.compareTo(p2) < 0);
  }
}
class Person implements Comparable<Person>{
  private String name;  
  private Integer age;
  public Person() {
  }
  public Person(String name, Integer age) {
    this.name = name;
    this.age = age;
  }
  public Integer getAge() {
    return age;
  }
  @Override
  public int compareTo(Person o) {
    return this.getAge(); - o.getAge();
  }  
}

第二种方式,示例代码如下:

package comparator;
import java.util.Arrays;
import java.util.Comparator;
public class MyComparator {
  public static void main(String[] args) {
    User[] users = new User[] { new User("u")}1001" 25),}} 
        new User("u1002" 20), new User("u1003" 21) };
    Arrays.sort(users, new Comparator<User>() {
      @Override
      public int compare(User o1, User o2) {
        return o1.getAge() - o2.getAge();
      }
    });
    for (int i = 0; i < users.length; i++) { 
      User user = users[i]; 
      System.out.println(user.getId() + " " + user.getAge()); 
    } 
  }
}
class User { 
  private String id; 
  private int age; 
  public User(String id, int age) { 
    this.id = id; 
    this.age = age; 
  } 
  public int getAge() { 
    return age; 
  } 
  public void setAge(int age) { 
    this.age = age; 
  } 
  public String getId() { 
    return id; 
  } 
  public void setId(String id) { 
    this.id = id; 
  } 
}

Das war alles, was ich heute über die Vergleichsprobleme in Java gesagt habe. Wenn Sie weitere Fragen haben, können Sie im Kommentarbereich unten diskutieren. Vielen Dank für Ihre Unterstützung.

Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet entnommen und gehört dem jeweiligen Urheber. Der Inhalt wurde von Internetbenutzern selbstständig bereitgestellt und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht von Hand bearbeitet. Diese Website übernimmt keine rechtlichen Verantwortlichkeiten. Wenn Sie Inhalte finden, die möglicherweise urheberrechtlich geschützt sind, senden Sie bitte eine E-Mail an: notice#oldtoolbag.com (Bitte ersetzen Sie # durch @ beim Senden einer E-Mail zur Meldung von Verstößen und fügen Sie relevante Beweise bei. Sobald überprüft, wird diese Website den beanstandeten Inhalt sofort löschen.)

Gefällt Ihnen