iterator() method automatically invoke - java

Im new to Collection java, and sorry if the questions are so basic.
While debugging a piece of codes in Shipment class. If return value in iterator() is null the test case is failed, but if returning values is products.iterator the test case is passed. So, I supposed that the iterator() method is automatically invoked when running the hasItem() in ShipmentTest class. But the strange is that it was invoked without calling from test file, like normal code
Iterator itr = al.iterator();
while(itr.hasNext()) {
Object element = itr.next();
// do something....
}
and the return type of hasItem() not return values related to iterator...
Anyone has experienced this case, can help share your ideas?
Here are the codes:
ShipmentTest class
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
public class ShipmentTest {
private Shipment shipment = new Shipment();
Product door = new Product("Door", 22);
Product windows = new Product("Windows", 10);
#Test
public void shouldAddItems() throws Exception {
shipment.add(door);
shipment.add(windows);
assertThat(shipment, hasItem(door));
}
}
Shipment class
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Shipment implements Iterable<Product> {
private static final int LIGHT_VAN_MAX_WEIGHT = 20;
private List<Product> products = new ArrayList<>();
#Override
public Iterator<Product> iterator() {
return products.iterator();
}
public void add(Product p) {
products.add(p);
}
}
Product class
public class Product {
private final String name;
private final int weight;
public Product(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public int getWeight() {
return weight;
}
#Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", weight=" + weight +
'}';
}
}

Yes, in order to test whether a collection contains an item, IsCollectionContaining.hasItem calls iterator(). That's a perfectly normal part of dealing with any Iterable. (How else could it tell whether the shipment contains a particular item?)

Related

Collections.sort() method not picking up overload method correctly

my goal is to sort the List of Persons. I am using compare method of Comparator interface.
I have created three classes. namely Person.java, AgeComparator.java, SortingExample.java.
Person class is a simple class with two fields (name, age) also with getters.
Then in my AgeComaparator class I have implement the Comparator interface and pass Person class as Type parameter.
then override the compare method which comes from Comparator interface.
so to execute this application, in my SortingExample I have created 3 objects of type Person.
then add those objects to ArrayList of type Person.
then called the Collections.sort() method which take two arguments.
those are list object and the class which implements Comparator interface.
Person.java
package com.nadee.module3;
import java.util.Objects;
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
Objects.requireNonNull(name);
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
#Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
AgeComparator.java
package com.nadee.module3;
import java.util.Comparator;
public class AgeComparator implements Comparator<Person>{
#Override
public int compare(Person left, Person right) {
return Integer.compare(left.getAge(), right.getAge());
}
}
SortingExample.java
package com.nadee.module3;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.nadee.collections.Person;
public class SortingExample {
public static void main(String[] args) {
Person p1 = new Person("will smith", 45);
Person p2 = new Person("john snow", 33);
Person p3 = new Person("johny depth", 55);
List<Person> actors = new ArrayList<Person>();
actors.add(p1);
actors.add(p2);
actors.add(p3);
System.out.println(actors);
Collections.sort(actors, new AgeComparator());
System.out.println(actors);
}
}
I'm using Eclipse IDE for this application and there is "red" line showing under the sort method.
the error is saying like following,
"The method sort(List, Comparator) in the type Collections is not applicable for the arguments (List, AgeComparator)"
I have followed the following article
https://www.journaldev.com/16094/java-collections-sort
what I'm doing wrong here ? any help would be much appreciated.
thanks
Class Person is located at com.nadee.module3 and class AgeComparator is using for this kind of Person
But in class SortingExample, you're using Person from com.nadee.collections.Person. It should totally not work.
Another point of your code:
Please using actors.sort(new AgeComparator());, Collections.sort is too common

How to look though a list of Objects to find a match?

I'm trying to compare a bunch of Objects of the same class to search for matching ID's?
This is the GroupClass, when a new entry is entered it will test against the idNumber to see if there is a match.
Public GroupClass {
private int idNumber;
private String name;
private double income;
public GroupClass(int id, String name, double income){
this.idNumber = id;
this.name = name;
this.income = income;
}
public int getIdNumber() {
return idNumber;
}
public void setIdNumber(int idNumber) {
this.idNumber = idNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
}
This is the Main Method
import static java.lang.reflect.Array.set;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class ListTester {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Set<GroupClass> groupArray = new LinkedHashSet<>();
System.out.println("Enter a ID Number");
int id = input.nextInt();
System.out.println("Enter a First Name");
String name = input.next();
System.out.println("Enter a an Income");
double income = input.nextDouble();
groupArray.add(new GroupClass(1111, "Billy", 178000));
groupArray.add(new GroupClass(1112, "Sam", 78000));
groupArray.add(new GroupClass(1113, "Mark", 79000));
groupArray.add(new GroupClass(id, name, income));
printTheClass(groupArray);
}
public static void printTheClass(Set group){
for(Object theArray: group){
System.out.println(theArray + " ");
}
}
}
Ive seen a few questions like it but just cant get it to work for my particular case, thanks in advance.
As per the above comment you override the equals method, but this may not be suitable for the long term growth of the class.
But using your existing code try
public static void printTheClass(Set<GroupClass> group){
for(GroupClass theArray: group){
System.out.println(theArray + " ");
}
}
and
public static GroupClass findTheClass(Set<GroupClass> group, int id){
for(GroupClass obj: group){
if(obj.getIdNumber == id) return obj;
}
return null;
}
This can be used as
if (findTheClass (groupArray, id) == null) {
groupArray.add (new GroupClass(id, name, income));
}
Not quite sure what is your goal. If you want to reject any new entry if the id already exist, you need to override the hashCode and equals methods of the GroupClass so that LinkedHashSet knows if two GroupClass objects are different:
#Override
public int hashCode() {
return this.idNumber;
}
#Override
public boolean equals(Object obj) {
return obj instanceof GroupClass && ((GroupClass) obj).getIdNumber() == this.idNumber;
}
However, in most cases, you might want to retrieve an entry using its id number. Then it might be better to use a map with id as key, and the GroupoClass object itself as value
Map<Integer, GroupClass> groupmap = new HashMap<>()
groupmap.put(id, new GroupClass(id, name, income));
and you will have to use groupmap.keySet() to iterate the map.

Collections.sort - I have created 2 user define objects [both are of different types] and then add into arraylist , then I have tried to sort it

Expected Result of code is ClassCastException but Actual Result :- [Person with pid- 1 - a1-name, Person with pid- 2 - c2-name, Sorting.Employee#cdfc9c, Sorting.Employee#1837697]
Person class:
package Sorting;
public class Person implements Comparable<Person> {
private int pid;
private String pname;
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
#Override
public String toString() {
return "Person with pid- " + getPid() + " - " + getPname();
}
#Override
public int compareTo(Person p) {
return this.pid - p.pid;
}
}
Employee class:
package Sorting;
public class Employee implements Comparable {
#Override
public int compareTo(Object o) {
return 0;
}
}
SortingofObjects class:
package Sorting;
import java.util.ArrayList;
import java.util.Collections;
public class SortingofObjects {
public static void main(String[] args) {
Person p1 = new Person();
p1.setPid(1);
p1.setPname("a1-name");
Person p2 = new Person();
p2.setPid(2);
p2.setPname("c2-name");
Employee e1 = new Employee();
Employee e2 = new Employee();
ArrayList a = new ArrayList();
a.add(p1);
a.add(p2);
a.add(e1);
a.add(e2);
Collections.sort(a);
System.out.println(a);
}
}
Collections.sort does not call compareTo on every pair in the List, just enough pairs to sort the List. As an example, run this code:
public class Test implements Comparable<Test> {
public static void main(String[] args) {
List<Test> list = new ArrayList<Test>();
list.add(new Test(1));
list.add(new Test(2));
list.add(new Test(3));
list.add(new Test(4));
Collections.sort(list);
}
private final int number;
Test(int number) {
this.number = number;
}
#Override
public int compareTo(Test that) {
System.out.println(this + ".compareTo(" + that + ")");
return 0;
}
#Override
public String toString() {
return "" + number;
}
}
The output is
2.compareTo(1)
3.compareTo(2)
4.compareTo(3)
Since your List is in the order Person, Person, Employee, Employee, the only combination that would throw a ClassCastException, namely
Person.compareTo(Employee)
never occurs. If your List contained an Employee before a Person it would throw an exception.
If it just so happens that the sorting algorithm used only compares Employees to Persons, and not the other way around, then it'll never throw, because Employee.compareTo accepts any Object. You just got lucky, more or less.

I want to alphabetize objects by a variable defined in its class

I am making a program that sets up an experiment for me and I want to alphabetize the subjects (or people) that i input. I have an arraylist of type subjects and i want to alphabetize them by their names.
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
public class Experiment
{
public Random number;
public ArrayList<String> allSubject;
public ArrayList<Subject> allSubjects,alphaSubjects;
public ArrayList<Group> experiment;
public Integer value;
public HashMap<Integer,Subject> matched;
private ArrayList<Integer> numbers;
/**
* Make a new Experiment. Then use method addSubject to add
* Subjects to your experiment. Then call the assignGroups
* method to assign Subjects to each group.
*/
public Experiment()
{
number = new Random();
numbers = new ArrayList<Integer>();
experiment = new ArrayList<Group>();
matched = new HashMap<Integer,Subject>();
allSubjects = new ArrayList<Subject>();
allSubject = new ArrayList<String>();
alphaSubjects = new ArrayList<Subject>();
}
/**
* Alphabetizes the list of Subjects based on their
* name input by the user. As of right now, this method
* is case sensitive meaning Strings starting with
* capitals will be listed before those without capitals.
*/
private void alphabetize()
{
Collections.sort(allSubject);
//compare the String arraylist to the subject arraylist to reset the subject arraylist indeces in alphabetical order.
for(int i =0;i<allSubject.size();i++)
{
String theName = allSubject.get(i);
for(Subject subject:allSubjects)
{
if(subject.getName().toLowerCase().contains(theName))
{
alphaSubjects.add(new Subject(subject.getName(),subject.getDescription()));
}
}
}
}
/**
* Adds a new Subject to the experiment.
*/
public void addSubject(String name, String description)
{
allSubjects.add(new Subject(name,description));
allSubject.add((name.toLowerCase()));
}
So instead of having to add a subject to an arraylist then having to strip the name from that subject and add it to a completely different arraylist, is there a way to alphabetize by the name of the subject.
oh and here is the class: subject.
public class Subject
{
public final String name;
public final String description;
public Subject(String name, String description)
{
this.name = name;
this.description = description;
}
public Subject(int aNumber)
{
name = "Subject" + aNumber;
aNumber++;
description = "default";
}
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
}
You can wrap subject ArrayList with SortedList(http://www.glazedlists.com/documentation/tutorial-100#TOC-Sorting-Tables-Sorting-Tables) using your own comparator.
SortedList sortedSubjects = new SortedList<Subject>(allSubjects,new Comparator<Subject>() {
#Override
public int compare(Subject left, Subject right) {
return left.getName().compareTo(right.getName);
}
});
All you need to do is have your class implement Comparable and add a compareTo():
public class Subject implements Comparable<Subject>
{
....
#Override
public int compareTo(Subject other)
{
return this.getName().compareTo(other.getName());
}
}
Now, since your class implements Comparable of itself, you can use Collections.sort() to sort your list of Subjects.
Here's a tutorial for more info. Good luck!
You can implement Comparator or Comparable and override compare(..) , compareTo(..) method as per your convince. In your case you need to consider 'name of the subject' while implementing this method. Then Collections.sort(yourList<Subject>) will give you sorted result based on subjects name.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Subject implements Comparable<Subject>
{
public final String name;
public final String description;
public Subject(String name, String description)
{
this.name = name;
this.description = description;
}
public Subject(int aNumber)
{
name = "Subject" + aNumber;
aNumber++;
description = "default";
}
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
#Override
public int compareTo(Subject o) {
return this.getName().toUpperCase().compareTo(((Subject)o).getName());
}
public static void main(String[] args) {
Subject s3 = new Subject("C","");
Subject s1 = new Subject("Z","");
Subject s2 = new Subject("A","");
List<Subject> list = new ArrayList<Subject>();
list.add(s1);
list.add(s2);
list.add(s3);
Collections.sort(list);
for(Subject sub:list){
System.out.println(sub.getName());
}
}
}

Java List sort on object fields constant values

I have a enum representing severity level
public enum Severity {
HIGH("H"), MEDIUM("M"), LOW("L");
}
Person one = new Person();
one.setSeverity(Severity.HIGH);
other fields ...
Person two = new Person();
two.setSeverity(Severity.LOW);
.....
Person three = new Person();
three.setSeverity(Severity.HIGH);
List<Person> persons = Lists.newArrayList();
persons.add(one);
persons.add(two);
persons.add(three);
I would like to sort persons list to sort by severity field (i.e HIGH,MEDIUM then LOW).
My expected results after sorting the persons list should be in the order of HIGH,HIGH,LOW ?
can i know how i can achieve this ?
note : I am making use of com.google.common.collect
Try below code
Create an ENUM
package com.rais;
public enum Severity {
HIGH("H"), MEDIUM("M"), LOW("L");
private final String value;
private Severity(String value) {
this.value = value;
}
}
Now Create Person class according to your requirement eg.
package com.rais;
public class Person {
private Severity severity;
private String name;
public Person(Severity severity, String name) {
super();
this.severity = severity;
this.name = name;
}
public Severity getSeverity() {
return severity;
}
public void setSeverity(Severity severity) {
this.severity = severity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Finally create a Test Client and apply below logic.
package com.rais;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TestClient {
public static void main(String[] args) {
Person one = new Person(Severity.HIGH, "shayam");
Person two = new Person(Severity.MEDIUM, "mohan");
Person three = new Person(Severity.LOW, "radha");
Person four = new Person(Severity.HIGH, "rakesh");
Person five = new Person(Severity.MEDIUM, "kailash");
Person six = new Person(Severity.LOW, "rais");
Person seven = new Person(Severity.LOW, "abhishek");
List<Person> persons = new ArrayList<Person>();
persons.add(one);
persons.add(two);
persons.add(three);
persons.add(four);
persons.add(five);
persons.add(six);
persons.add(seven);
Collections.sort(persons, new Comparator<Person>() {
#Override
public int compare(Person person1, Person person2) {
if(person1.getSeverity()==person2.getSeverity())
{
return person1.getName().compareTo(person2.getName());
}
else{
return person1.getSeverity().compareTo(person2.getSeverity());
}
}
});
for (Person person : persons) {
System.out.println(person.getName()+" "+ person.getSeverity());
}
}
}
I am sure you will get below output.
rakesh HIGH
shayam HIGH
kailash MEDIUM
mohan MEDIUM
abhishek LOW
radha LOW
rais LOW
Use Comparable or comparator and then apply
Collection.sort().
if using comparable interface you have to implement compareTo method and
Collection.sort(<list>)
and if using comparator then you have to override compareTo method and
Collection.sort(<list>, <comparator>)
and when to use comparatot or comparable read link:
http://iandjava.blogspot.in/2012/10/comparable-and-comparator.html
If you are using Google Collections, upgrade to Google Guava. Use its ComparisonChain class. Are you sure you want HIGH, MEDIUM, LOW in that order? The reverse fits Java comparisons better.
How do Persons have a severity level? Perhaps your class deserves a better name.
I would make Person implement Comparable, which makes the sorting code very simple and brief.
Note that enums are implicitly Comparable:
public enum Severity {
HIGH("H"), MEDIUM("M"), LOW("L");
private final String code;
private Severity(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
public class Person implements Comparable<Person> {
private Severity severity;
private final String name;
public Person(Severity severity, String name) {
this.severity = severity;
this.name = name;
}
public Severity getSeverity() {
return severity;
}
public void setSeverity(Severity severity) {
this.severity = severity;
}
public String getName() {
return name;
}
#Override
public int compareTo(Person person) {
return severity == person.severity ? name.compareTo(person.name)
: severity.compareTo(person.severity);
}
#Override
public String toString() {
return name + "(" + severity +")";
}
}
Now some test code:
Person one = new Person(Severity.HIGH, "one");
Person two = new Person(Severity.LOW, "two");
Person three = new Person(Severity.HIGH, "three");
List<Person> persons = new ArrayList<Person>();
persons.add(one);
persons.add(two);
persons.add(three);
Collections.sort(persons);
System.out.println(persons);
Output:
[one(HIGH), three(HIGH), two(LOW)]

Categories