The Comparator interface in Java is a powerful tool for defining custom sorting logic for objects; COMPARE.EDU.VN provides a comprehensive guide to help you master it. It enables sorting based on specific criteria, offering flexibility beyond the natural ordering. Explore this guide to learn how to implement and utilize the Comparator interface effectively, and discover alternative sorting methods.
1. Understanding the Comparator Interface in Java
What is the Comparator interface in Java, and how does it facilitate custom sorting? The Comparator interface in Java is a functional interface that defines a method for comparing two objects. It provides a way to sort collections of objects based on custom criteria, enabling developers to define specific sorting logic that goes beyond the natural ordering of objects. This interface is particularly useful when you need to sort objects in a way that is not inherently supported by the object’s class or when you want to provide multiple sorting options.
1.1. Definition of the Comparator Interface
The Comparator interface is a part of the java.util
package and is defined as follows:
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
The interface contains two primary methods:
compare(T o1, T o2)
: This method compares two objects of typeT
and returns an integer value. The return value indicates the relative order of the objects:- A negative value if
o1
should come beforeo2
. - A positive value if
o1
should come aftero2
. - Zero if
o1
ando2
are equal in terms of sorting.
- A negative value if
equals(Object obj)
: This method checks whether the comparator is equal to another object. While it’s part of the Comparator interface, it’s often inherited from theObject
class and doesn’t need to be explicitly implemented unless you’re defining specific equality rules for comparators.
1.2. Purpose of the Comparator Interface
The primary purpose of the Comparator interface is to provide a flexible mechanism for sorting collections of objects according to custom rules. It addresses several key needs in software development:
- Custom Sorting Logic: Allows developers to define specific sorting criteria that are not based on the natural ordering of objects.
- Multiple Sorting Options: Enables the same collection to be sorted in different ways by using different Comparator implementations.
- Sorting Objects Without Natural Ordering: Provides a way to sort objects that do not implement the
Comparable
interface or for which the natural ordering is not suitable. - Decoupling Sorting Logic: Separates the sorting logic from the object’s class, promoting better code organization and reusability.
1.3. How the Comparator Interface Works
The Comparator interface works by providing a standard contract for comparing objects. Here’s how it generally works:
- Implement the Comparator Interface: Create a class that implements the
Comparator<T>
interface, whereT
is the type of objects you want to compare. - Implement the
compare()
Method: Provide an implementation for thecompare(T o1, T o2)
method. This method contains the custom sorting logic. - Use with Sorting Methods: Pass an instance of your Comparator implementation to sorting methods like
Collections.sort()
orArrays.sort()
to sort a collection of objects.
1.4. Example of Comparator Interface
Consider a scenario where you have a list of Student
objects, and you want to sort them based on their names. Here’s how you can use the Comparator interface to achieve this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
class SortByName implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
public class Main {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 22));
students.add(new Student("Charlie", 19));
System.out.println("Before sorting: " + students);
Collections.sort(students, new SortByName());
System.out.println("After sorting by name: " + students);
}
}
In this example:
- The
Student
class represents student objects withname
andage
attributes. - The
SortByName
class implements theComparator<Student>
interface and provides an implementation for thecompare()
method, which compares students based on their names. - The
Collections.sort()
method is used to sort the list of students using theSortByName
comparator.
1.5. Key Benefits of Using Comparator
Using the Comparator interface offers several benefits:
- Flexibility: Allows for custom sorting logic tailored to specific needs.
- Reusability: Comparators can be reused across different parts of the application.
- Decoupling: Separates sorting logic from the object’s class, improving code maintainability.
- Multiple Sorting Options: Enables the same collection to be sorted in different ways by providing different Comparator implementations.
1.6. Conclusion
The Comparator interface in Java is a powerful and flexible tool for defining custom sorting logic for collections of objects. By understanding its purpose, implementation, and benefits, developers can effectively use it to sort objects based on specific criteria, providing more control over the sorting process and improving code organization. At COMPARE.EDU.VN, we understand the importance of flexibility in sorting, providing detailed comparisons and guidelines to help you make informed decisions. For any inquiries, reach out to us at: Address: 333 Comparison Plaza, Choice City, CA 90210, United States. Whatsapp: +1 (626) 555-9090. Website: COMPARE.EDU.VN.
2. Implementing the Comparator Interface
How do you implement the Comparator interface to define custom sorting logic in Java? Implementing the Comparator interface involves creating a class that provides a specific comparison logic for objects of a particular type. This implementation allows you to sort collections of objects based on criteria that are not inherently supported by the object’s class. Here’s a detailed guide on how to implement the Comparator interface effectively.
2.1. Steps to Implement the Comparator Interface
To implement the Comparator interface, follow these steps:
- Create a Class: Define a new class that will implement the
Comparator<T>
interface, whereT
is the type of objects you want to compare. - Implement the
compare()
Method: Provide an implementation for thecompare(T o1, T o2)
method. This method should contain the custom sorting logic. - Instantiate and Use: Create an instance of your Comparator class and pass it to sorting methods like
Collections.sort()
orArrays.sort()
to sort a collection of objects.
2.2. Detailed Explanation of the Implementation Process
Let’s delve into each step with a more detailed explanation.
Step 1: Create a Class
Start by creating a new class that implements the Comparator<T>
interface. Replace T
with the actual type of objects you want to compare.
import java.util.Comparator;
class MyObjectComparator implements Comparator<MyObject> {
// Implementation of the compare() method will go here
}
In this example, MyObjectComparator
is the class that will implement the Comparator
interface for objects of type MyObject
.
Step 2: Implement the compare()
Method
The core of the Comparator implementation is the compare(T o1, T o2)
method. This method defines the logic for comparing two objects and determining their relative order.
import java.util.Comparator;
class MyObjectComparator implements Comparator<MyObject> {
@Override
public int compare(MyObject o1, MyObject o2) {
// Custom comparison logic here
}
}
Inside the compare()
method, you need to provide the comparison logic based on the attributes or properties of the objects. The method should return:
- A negative value if
o1
should come beforeo2
. - A positive value if
o1
should come aftero2
. - Zero if
o1
ando2
are equal in terms of sorting.
Here’s an example of comparing MyObject
instances based on a numeric attribute:
import java.util.Comparator;
class MyObject {
private int value;
public MyObject(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
class MyObjectComparator implements Comparator<MyObject> {
@Override
public int compare(MyObject o1, MyObject o2) {
return Integer.compare(o1.getValue(), o2.getValue());
}
}
In this case, the compare()
method uses Integer.compare()
to compare the value
attributes of the two MyObject
instances.
Step 3: Instantiate and Use
After implementing the Comparator, you need to create an instance of it and use it with sorting methods like Collections.sort()
or Arrays.sort()
.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<MyObject> objects = new ArrayList<>();
objects.add(new MyObject(3));
objects.add(new MyObject(1));
objects.add(new MyObject(2));
System.out.println("Before sorting: " + objects);
Collections.sort(objects, new MyObjectComparator());
System.out.println("After sorting: " + objects);
}
}
In this example, a list of MyObject
instances is created and sorted using the MyObjectComparator
.
2.3. Example: Sorting Students by Multiple Criteria
Consider a more complex scenario where you want to sort a list of Student
objects by name and then by age. Here’s how you can implement a Comparator to achieve this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
class SortByNameThenAge implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
int nameComparison = s1.getName().compareTo(s2.getName());
if (nameComparison != 0) {
return nameComparison;
} else {
return Integer.compare(s1.getAge(), s2.getAge());
}
}
}
public class Main {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 22));
students.add(new Student("Alice", 19));
students.add(new Student("Charlie", 19));
System.out.println("Before sorting: " + students);
Collections.sort(students, new SortByNameThenAge());
System.out.println("After sorting by name then age: " + students);
}
}
In this example:
- The
SortByNameThenAge
class implements theComparator<Student>
interface. - The
compare()
method first compares students by name. If the names are different, it returns the result of the name comparison. If the names are the same, it compares the students by age.
2.4. Using Lambda Expressions for Comparators
In Java 8 and later, you can use lambda expressions to create comparators more concisely. Here’s how you can rewrite the previous example using a lambda expression:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 22));
students.add(new Student("Alice", 19));
students.add(new Student("Charlie", 19));
System.out.println("Before sorting: " + students);
Collections.sort(students, (s1, s2) -> {
int nameComparison = s1.getName().compareTo(s2.getName());
if (nameComparison != 0) {
return nameComparison;
} else {
return Integer.compare(s1.getAge(), s2.getAge());
}
});
System.out.println("After sorting by name then age: " + students);
}
}
This lambda expression achieves the same result as the SortByNameThenAge
class but with fewer lines of code.
2.5. Key Considerations When Implementing Comparators
- Null Handling: Ensure your Comparator handles null values appropriately to avoid NullPointerExceptions.
- Consistency: The comparison logic should be consistent, meaning that if
compare(a, b)
returns a negative value, thencompare(b, a)
should return a positive value. - Transitivity: The comparison logic should be transitive, meaning that if
compare(a, b)
returns a negative value andcompare(b, c)
returns a negative value, thencompare(a, c)
should also return a negative value. - Performance: Be mindful of the performance implications of your comparison logic, especially when sorting large collections.
2.6. Conclusion
Implementing the Comparator interface in Java allows you to define custom sorting logic for collections of objects. By following the steps outlined in this guide, you can effectively implement Comparators to sort objects based on specific criteria, providing more control over the sorting process. At COMPARE.EDU.VN, we provide thorough evaluations of various sorting techniques, ensuring you have the knowledge to make well-informed decisions. For more information, contact us at: Address: 333 Comparison Plaza, Choice City, CA 90210, United States. Whatsapp: +1 (626) 555-9090. Website: COMPARE.EDU.VN.
3. Using the Comparator Interface with Collections
How do you effectively use the Comparator interface with Java Collections to sort data according to custom rules? The Comparator interface is a powerful tool when working with Java Collections, enabling you to sort data in various ways based on custom criteria. This section will guide you through the process of using the Comparator interface with Collections, providing practical examples and best practices.
3.1. Sorting Collections with Collections.sort()
The Collections.sort()
method is a fundamental part of the Java Collections Framework, allowing you to sort lists using a specified Comparator. Here’s how you can use it:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class MyObject {
private int value;
public MyObject(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "MyObject{" +
"value=" + value +
'}';
}
}
class MyObjectComparator implements Comparator<MyObject> {
@Override
public int compare(MyObject o1, MyObject o2) {
return Integer.compare(o1.getValue(), o2.getValue());
}
}
public class Main {
public static void main(String[] args) {
List<MyObject> objects = new ArrayList<>();
objects.add(new MyObject(3));
objects.add(new MyObject(1));
objects.add(new MyObject(2));
System.out.println("Before sorting: " + objects);
Collections.sort(objects, new MyObjectComparator());
System.out.println("After sorting: " + objects);
}
}
In this example, Collections.sort()
is used to sort a list of MyObject
instances using the MyObjectComparator
.
3.2. Sorting Collections with Lambda Expressions
Java 8 introduced lambda expressions, providing a more concise way to define comparators directly within the Collections.sort()
method.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<MyObject> objects = new ArrayList<>();
objects.add(new MyObject(3));
objects.add(new MyObject(1));
objects.add(new MyObject(2));
System.out.println("Before sorting: " + objects);
Collections.sort(objects, (o1, o2) -> Integer.compare(o1.getValue(), o2.getValue()));
System.out.println("After sorting: " + objects);
}
}
This lambda expression achieves the same result as the MyObjectComparator
class but with fewer lines of code.
3.3. Sorting Different Types of Collections
The Comparator interface can be used with various types of collections, including ArrayList
, LinkedList
, and others. Here’s an example with a LinkedList
:
import java.util.LinkedList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<MyObject> objects = new LinkedList<>();
objects.add(new MyObject(3));
objects.add(new MyObject(1));
objects.add(new MyObject(2));
System.out.println("Before sorting: " + objects);
Collections.sort(objects, (o1, o2) -> Integer.compare(o1.getValue(), o2.getValue()));
System.out.println("After sorting: " + objects);
}
}
The Collections.sort()
method works seamlessly with different types of lists, making the Comparator interface a versatile tool.
3.4. Sorting Custom Objects
Sorting custom objects involves defining a Comparator that compares the attributes of those objects. Consider a Person
class with attributes like name
and age
:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
System.out.println("Before sorting: " + people);
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));
System.out.println("After sorting by name: " + people);
}
}
In this example, the list of Person
objects is sorted by name using a lambda expression that compares the name
attributes.
3.5. Using the Comparator Interface with Streams
Java Streams provide another way to sort collections using the Comparator interface. The sorted()
method in the Stream API allows you to sort elements based on a specified Comparator.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
System.out.println("Before sorting: " + people);
List<Person> sortedPeople = people.stream()
.sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
.collect(Collectors.toList());
System.out.println("After sorting by name: " + sortedPeople);
}
}
This example uses the Stream API to sort a list of Person
objects by name and collect the sorted elements into a new list.
3.6. Combining Multiple Comparators
You can combine multiple comparators to sort collections based on multiple criteria. Here’s an example of sorting a list of Person
objects first by name and then by age:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Alice", 25));
people.add(new Person("Charlie", 35));
System.out.println("Before sorting: " + people);
Collections.sort(people, (p1, p2) -> {
int nameComparison = p1.getName().compareTo(p2.getName());
if (nameComparison != 0) {
return nameComparison;
} else {
return Integer.compare(p1.getAge(), p2.getAge());
}
});
System.out.println("After sorting by name then age: " + people);
}
}
This example sorts the list of Person
objects first by name and then by age if the names are the same.
3.7. Best Practices for Using Comparators with Collections
- Handle Null Values: Ensure your comparator handles null values appropriately to avoid NullPointerExceptions.
- Ensure Consistency: The comparison logic should be consistent, meaning that if
compare(a, b)
returns a negative value, thencompare(b, a)
should return a positive value. - Consider Performance: Be mindful of the performance implications of your comparison logic, especially when sorting large collections.
- Use Lambda Expressions: Use lambda expressions for simple comparators to make your code more concise and readable.
3.8. Conclusion
Using the Comparator interface with Java Collections provides a flexible and powerful way to sort data according to custom rules. Whether you’re using Collections.sort()
, Java Streams, or combining multiple comparators, understanding how to effectively implement and use Comparators will greatly enhance your ability to manage and manipulate data. At COMPARE.EDU.VN, we offer detailed analyses and comparisons of different sorting methods to help you optimize your data handling strategies. For further assistance, please contact us at: Address: 333 Comparison Plaza, Choice City, CA 90210, United States. Whatsapp: +1 (626) 555-9090. Website: COMPARE.EDU.VN.
4. Comparator vs. Comparable: Key Differences
What are the key differences between the Comparator and Comparable interfaces in Java, and when should you use each? Both the Comparator and Comparable interfaces in Java are used for sorting objects, but they serve different purposes and have distinct characteristics. Understanding their differences is crucial for choosing the right approach for your sorting needs. Here’s a comprehensive comparison to help you differentiate between the two.
4.1. Definition and Purpose
- Comparable Interface:
- Definition: The
Comparable
interface is defined in thejava.lang
package and is used to define the natural ordering of objects. - Purpose: It allows an object to compare itself with another object of the same type.
- Definition: The
- Comparator Interface:
- Definition: The
Comparator
interface is defined in thejava.util
package and is used to define a custom ordering for objects. - Purpose: It provides a way to compare two different objects based on specific criteria.
- Definition: The
4.2. Implementation
- Comparable Interface:
- Implementation: To use the
Comparable
interface, a class must implement the interface and provide an implementation for thecompareTo()
method. - Method:
int compareTo(T o)
- Implementation: To use the
- Comparator Interface:
- Implementation: To use the
Comparator
interface, you create a separate class that implements theComparator
interface and provides an implementation for thecompare()
method. - Method:
int compare(T o1, T o2)
- Implementation: To use the
4.3. Usage
-
Comparable Interface:
-
Usage: When a class implements the
Comparable
interface, its objects can be sorted using methods likeCollections.sort()
orArrays.sort()
without providing an explicit comparator. -
Example:
import java.util.ArrayList; import java.util.Collections; import java.util.List; class MyObject implements Comparable<MyObject> { private int value; public MyObject(int value) { this.value = value; } public int getValue() { return value; } @Override public int compareTo(MyObject o) { return Integer.compare(this.value, o.value); } @Override public String toString() { return "MyObject{" + "value=" + value + '}'; } } public class Main { public static void main(String[] args) { List<MyObject> objects = new ArrayList<>(); objects.add(new MyObject(3)); objects.add(new MyObject(1)); objects.add(new MyObject(2)); System.out.println("Before sorting: " + objects); Collections.sort(objects); System.out.println("After sorting: " + objects); } }
-
-
Comparator Interface:
-
Usage: When using the
Comparator
interface, you need to provide an instance of the Comparator to the sorting methods. -
Example:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; class MyObject { private int value; public MyObject(int value) { this.value = value; } public int getValue() { return value; } @Override public String toString() { return "MyObject{" + "value=" + value + '}'; } } class MyObjectComparator implements Comparator<MyObject> { @Override public int compare(MyObject o1, MyObject o2) { return Integer.compare(o1.getValue(), o2.getValue()); } } public class Main { public static void main(String[] args) { List<MyObject> objects = new ArrayList<>(); objects.add(new MyObject(3)); objects.add(new MyObject(1)); objects.add(new MyObject(2)); System.out.println("Before sorting: " + objects); Collections.sort(objects, new MyObjectComparator()); System.out.println("After sorting: " + objects); } }
-
4.4. Flexibility
- Comparable Interface:
- Flexibility: Provides a single, natural way to compare objects. It is less flexible because it is part of the class definition and cannot be changed without modifying the class.
- Comparator Interface:
- Flexibility: Offers greater flexibility because you can create multiple Comparators to sort objects in different ways without modifying the class.
4.5. When to Use
- Comparable Interface:
- When to Use: Use the
Comparable
interface when you want to define the natural ordering of objects and when you have control over the class definition. - Use Cases:
- Sorting objects based on a primary attribute.
- Defining the default sorting behavior for a class.
- When to Use: Use the
- Comparator Interface:
- When to Use: Use the
Comparator
interface when you need to sort objects in different ways or when you don’t have control over the class definition. - Use Cases:
- Sorting objects based on multiple attributes.
- Sorting objects in a way that is not their natural ordering.
- Sorting objects from third-party libraries without modifying their code.
- When to Use: Use the
4.6. Key Differences Summarized
Feature | Comparable | Comparator |
---|---|---|
Definition | Part of java.lang |
Part of java.util |
Purpose | Defines natural ordering | Defines custom ordering |
Implementation | Implemented by the class itself | Implemented by a separate class |
Method | compareTo(T o) |
compare(T o1, T o2) |
Flexibility | Less flexible; defines a single sorting order | More flexible; allows multiple sorting orders |
Usage | Collections.sort(list) |
Collections.sort(list, comparator) |
Control | Requires control over the class definition | Does not require control over the class definition |
4.7. Example Scenario
Consider a scenario with a Book
class.
- If you want to define the natural ordering of books based on their title, you would implement the
Comparable
interface in theBook
class. - If you want to sort books by author, publication date, or any other criteria, you would create separate classes that implement the
Comparator
interface.
4.8. Conclusion
The Comparator and Comparable interfaces in Java serve different purposes in sorting objects. The Comparable
interface is used to define the natural ordering of objects, while the Comparator
interface is used to define custom sorting logic. Understanding their differences and knowing when to use each will help you write more flexible and maintainable code. At COMPARE.EDU.VN, we provide detailed comparisons of various sorting techniques to help you optimize your data handling strategies. For further assistance, please contact us at: Address: 333 Comparison Plaza, Choice City, CA 90210, United States. Whatsapp: +1 (626) 555-9090. Website: compare.edu.vn.
5. Practical Examples of Comparator Interface
Can you provide practical examples of how the Comparator interface is used in real-world scenarios? The Comparator interface in Java is widely used in real-world scenarios to provide custom sorting logic for various types of objects. Here are several practical examples demonstrating how the Comparator interface can be applied to solve common sorting problems.
5.1. Sorting a List of Employees by Salary
Consider a scenario where you have a list of Employee
objects, and you want to sort them based on their salary.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + ''' +
", salary=" + salary +
'}';
}
}
public class Main {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("Alice", 50000));
employees.add(new Employee("Bob", 60000));
employees.add(new Employee("Charlie", 45000));
System.out.println("Before sorting: " + employees);
Collections.sort(employees, Comparator.comparingDouble(Employee::getSalary));
System.out.println("After sorting by salary: " + employees);
}
}
In this example, the Comparator.comparingDouble()
method is used to create a Comparator that compares employees based on their salary.
5.2. Sorting a List of Products by Price and Then by Name
Consider a scenario where you have a list of Product
objects, and you want to sort them first by price (in ascending order) and then by name (in alphabetical order).
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + ''' +
", price=" + price +
'}';
}
}
public class Main {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product("Laptop", 1200));
products.add(new Product("Tablet", 300));
products.add(new Product("Phone", 800));
products.add(new Product("Charger",