I have input of multiple strings where I parse each one to fetch certain data and then display them accordingly. The point is I need to sort them accodring to some parameters before displaying them.
To clarify:
String s1 = "a1 5 2014-12-05";
String s2 = "a2 10 2014-12-06";
String s3 = "a3 5 2014-12-04":
After pasring each string, I need to sort them descendingly first according to the second parameter and then according to the date whenever I reach a tie for example.
Output should be:
a2, a1, a3
Any idea how can this be achieved or if I could change the way to a more efficient one?!
You can parse the data and use Collections#sort. Your class can define some natural ordering using Comparable and in case if you want to sort descending then just pass Comparator.reverseOrder() as second arg to Collections#sort like this
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
public class DateSorter {
static class Entry implements Comparable<Entry> {
String id;
int num;
Date date;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public Entry(String id, int num, String date) throws ParseException {
this.id = id;
this.num = num;
this.date = sdf.parse(date);
}
#Override
public int compareTo(Entry o) {
return date.compareTo(o.date);
}
#Override
public String toString() {
return id + '\'';
}
}
public static void main(String[] args) throws ParseException {
String s1 = "a1 5 2014-12-05";
String s2 = "a2 10 2014-12-06";
String s3 = "a3 5 2014-12-04";
String[] split = s1.split(" ");
List<Entry> entries = new ArrayList<>();
entries.add(new Entry(split[0], Integer.parseInt(split[1]), split[2]));
split = s2.split(" ");
entries.add(new Entry(split[0], Integer.parseInt(split[1]), split[2]));
split = s3.split(" ");
entries.add(new Entry(split[0], Integer.parseInt(split[1]), split[2]));
Collections.sort(entries, new Comparator<Entry>() {
#Override
public int compare(Entry o1, Entry o2) {
return o2.compareTo(o1);
}
});
System.out.println(entries);
}
}
Output
[a2', a1', a3']
Related
I want to return actor older than a certain age limit using Java Stream filter function, but my code returned an error message
Line 63: error: cannot find symbol [in Actor.java]
.filter(actor -> actor.getAge > ageLimit)
symbol: variable getAge
location: variable actor of type Actor
My code is as below:
import java.util.*;
import java.io.*;
import java.nio.*;
import java.math.*;
import java.time.chrono.IsoChronology;
import java.time.LocalDate;
import java.util.stream.Collectors;
class Actor {
String name;
LocalDate birthday;
Actor(String nameArg, LocalDate birthdayArg) {
name = nameArg;
birthday = birthdayArg;
}
public int getAge() {
return birthday
.until(IsoChronology.INSTANCE.dateNow())
.getYears();
}
public String getName() {
return name;
}
public static List<Actor> createCast() {
List<Actor> cast = new ArrayList();
cast.add(
new Actor(
"Fred",
IsoChronology.INSTANCE.date(1980, 6, 20)));
cast.add(
new Actor(
"0mar",
IsoChronology.INSTANCE.date(1990, 12, 10)));
return cast;
}
public void printActor() {
System.out.println(name + ", " + this.getAge()); }
}
class cast {
interface CheckPerson {
boolean test (Actor p);
}
public static void printActors (List<Actor> cast) {
for (Actor p: cast) {
p.printActor();
}
}
public static List<Actor> getActorsolderThan(List<Actor> cast, int ageLimit) {
List<Actor> result = cast.stream() // convert list to stream
.filter(actor -> actor.getAge > ageLimit) //TODO
.collect(Collectors. toList());
return result;
}
}
The test code is as below:
//Test Code:
List<Actor> cast = Actor.createCast();
List<Actor> castolderThan = Cast.getActorsolderThan(cast, 30);
Cast.printActors(cast);
May I ask how exactly should I use filter function to return actor older than a certain age limit by editing the code on the filter line in the getActorsolderThan method?
I think this line should be like this
List<Actor> result = cast.stream() // convert list to stream
.filter(actor -> actor.getAge() > 100) //TODO
.collect(Collectors. toList());
getAge is a function not a class variable
I have the following problem to solve. I am using Java.
A restaurant recognizes 3 types of customers: “NEWBIES”, “REGULARS” and “VIPs”. When customers place their orders, all the orders join a queue. However the orders are always served in such a way that VIPs are served before regulars who are served before newbies.
I need a class which could be used to sort the customer orders. In case two customers are of the same type, the orderID should be used to sort them.
How can I sort by order priority based on the customer type using comparator?
Assuming I already have the following class Order
public class Order
{
public static int orderID;
private int tableNumber;
private String[] orderDetails;
private String customerType;
public Order(int tableNumber, String[] orderDetails, String customerType)
{
this.tableNumber = tableNumber;
this.orderDetails = orderDetails;
this.customerType = customerType;
orderID += 1;
}
// get and set methods declared
}
I have implemented the comparator as follows:
import java.util.Comparator;
public class OrderComparator implements Comparator<Order>
{
#Override
public int compare(Order o1, Order o2)
{
if(o1.getType().equals(o2.getType()))
return o1.getOrderID - o2.getOrderID;
else
// How does comparing the customer type text ensure that
// it will be printed in the right order?
return o1.getType().compareTo(o2.getType());
}
}
Not only do you want to sort on multiple fields, you also want a custom sort with one of those fields.
In the code below, I filled in the missing parts of both class Order and class OrderComparator. Notes after the code.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Order {
public static final String NEWBIES = "NEWBIES";
public static final String REGULARS = "REGULARS";
public static final String VIP = "VIP";
private static int orderId;
private int orderID;
private int tableNumber;
private String[] orderDetails;
private String customerType;
public Order(int tableNumber, String[] orderDetails, String customerType) {
this.tableNumber = tableNumber;
this.orderDetails = orderDetails;
this.customerType = customerType;
orderID = ++orderId;
}
public int getOrderID() {
return orderID;
}
public int getTableNumber() {
return tableNumber;
}
public String[] getOrderDetails() {
return orderDetails;
}
public String getType() {
return customerType;
}
public String toString() {
return String.format("%d %s", orderID, customerType);
}
public static void main(String[] args) {
Order order1 = new Order(0, null, VIP);
Order order2 = new Order(0, null, REGULARS);
Order order3 = new Order(0, null, REGULARS);
List<Order> list = new ArrayList<>();
list.add(order3);
list.add(order2);
list.add(order1);
System.out.println("Unordered: " + list);
Collections.sort(list, new OrderComparator());
System.out.println("Ordered: " + list);
}
}
class OrderComparator implements Comparator<Order> {
#Override
public int compare(Order o1, Order o2) {
if (o1.getType().equals(o2.getType())) {
return o1.getOrderID() - o2.getOrderID();
}
else {
if (Order.VIP.equals(o1.getType())) {
return -1;
}
else if (Order.VIP.equals(o2.getType())) {
return 1;
}
else if (Order.REGULARS.equals(o1.getType())) {
return -1;
}
else if (Order.REGULARS.equals(o2.getType())) {
return 1;
}
else if (Order.NEWBIES.equals(o1.getType())) {
return -1;
}
else if (Order.NEWBIES.equals(o2.getType())) {
return 1;
}
throw new RuntimeException("Unexpected customer type.");
}
}
}
I added method main to class Order in order to test the code.
I added method toString to class Order so as to be able to check whether the code produces the expected results.
I understand that you want a kind of numerator for Order objects. Hence I made member orderID an instance member since every Order has its own ID and I added a new static member orderId (note that Java is case sensitive) which produces a new, unique order ID for each new Order object.
You want VIP orders to come before REGULARS orders and you want REGULARS orders to come before NEWBIES orders. By default, a Comparator sorts by ascending order, hence you want VIP to be lowest and NEWBIES to be highest (purely for sorting purposes). So in method compare (of class OrderComparator), if, for example, the type of o1 is VIP and the type of o2 is REGULARS then you want VIP to be lower that REGULAR. Hence in that situation, method compare returns -1 (minus one).
Running the above code produces the following output.
Unordered: [3 REGULARS, 2 REGULARS, 1 VIP]
Ordered: [1 VIP, 2 REGULARS, 3 REGULARS]
Note that since customerType (in class Order) is a String, there is a chance that an Order object will be created with an invalid customerType value. You could change the constructor of class Order and add a check for the supplied value (for customerType) and throw an Exception if the supplied value is invalid. Or you could use enum (also known as enumerated types). The below code uses enum instead of String for customerType - which also simplifies method compare in class OrderComparator.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Order {
private static int orderId;
private int orderID;
private int tableNumber;
private String[] orderDetails;
private CustomerType customerType;
public Order(int tableNumber, String[] orderDetails, CustomerType customerType) {
this.tableNumber = tableNumber;
this.orderDetails = orderDetails;
this.customerType = customerType;
orderID = ++orderId;
}
public int getOrderID() {
return orderID;
}
public int getTableNumber() {
return tableNumber;
}
public String[] getOrderDetails() {
return orderDetails;
}
public CustomerType getType() {
return customerType;
}
public String toString() {
return String.format("%d %s", orderID, customerType);
}
public static void main(String[] args) {
Order order1 = new Order(0, null, CustomerType.VIP);
Order order2 = new Order(0, null, CustomerType.REGULARS);
Order order3 = new Order(0, null, CustomerType.REGULARS);
List<Order> list = new ArrayList<>();
list.add(order3);
list.add(order2);
list.add(order1);
System.out.println("Unordered: " + list);
Collections.sort(list, new OrderComparator());
System.out.println("Ordered: " + list);
}
}
class OrderComparator implements Comparator<Order> {
#Override
public int compare(Order o1, Order o2) {
if (o1.getType().equals(o2.getType())) {
return o1.getOrderID() - o2.getOrderID();
}
else {
return o2.getType().ordinal() - o1.getType().ordinal();
}
}
}
enum CustomerType {
NEWBIES, REGULARS, VIP
}
You can read this question How to sort a collection by multiple fields. Especially the second answer, first option listed.
I would like to return the values of all the attributes from the BaseballPlayer class. The method that needs to do this must be the public string getBaseballPlayer(int i) method (because I need to reference this method inside getBaseballPlayers() to return all the values as an arraylist of strings) I'm having trouble doing this because all the attributes have different datatypes (int, String, Height).
I've tried doing this:
public String getBaseballPlayer(int i){
ArrayList <String> bArray = new ArrayList <String>();
bArray.add(getHometown());
bArray.add(getState());
bArray.add(getHighSchool());
bArray.add(getPosition());
However, it only works for the string methods, and doesn't necessarily return the actual values but rather the get methods for each string attribute.
public class BaseballPlayer extends Player implements Table {
private int num;
private String pos;
public BaseballPlayer( int a, String b, String c, int d,
String e, String f, String g, Height h){
super(a,ft,in,c,d,e,f,ht);
num = a;
pos = b;
}
public BaseballPlayer(){}
//Returns the value of a specific attribute. The input parameter start
with 0 for the first attribute, then 1 for the second attribute and so
on.
//you can use getBaseballPlayer(int i) in getBaseballPlayers( ) with a for
loop getting each getBaseballPlayer(int i).
public String getBaseballPlayer(int i){
ArrayList <String> bArray = new ArrayList <String>();
bArray.add(getHometown());
bArray.add(getState());
bArray.add(getHighSchool());
bArray.add(getPosition());
return (bArray);
}
//Returns the value of all attributes as an ArrayList of Strings.
public ArrayList <String> getBaseballPlayers(){
}
I'm just looking for the simplest way to return each attributes value, then using that method return each value as an arraylist of strings in another method.
It is not a good practice to return the whole object as one String. Unless and otherwise, you are forced to do this, do not try and do.
Well, if your requirement can't be changed, and if you want everything from the Baseball object to be in one string, you can concatenate all the parameters with a delimiter like ":".
Eg:
public String getBaseballPlayer(int i){
return getHometown() + ":" + getState() + ":" +getHighSchool() + ":" + getPosition();
}
On the invoking side, you can get the individual values from this String using "split()" method of String.
What you want to do, if you want to do it perfectly, is what Gson is for. It rides on top of simple JSON and can encode arbitrary classes, data structures, and other types into JSON such that you can reconstruct those objects easily from the JSON representation. It's easy to use considering how powerful what it does really is.
It's even easier to use regular JSON if you don't need to encode types that JSON won't handle by itself. In your case, it seems that this could be good enough. The great thing about JSON is that it's a standard. You don't have to choose an encoding scheme, and you already have libraries written in any language you can think of that can read your String'ified data.
Here's an example that roughly follows what your code is doing:
import org.codehaus.jackson.map.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
public class BaseballPlayer {
private String name;
private String hometown;
private String state;
private int age;
private double height;
private String position;
static ObjectMapper mapper = new ObjectMapper();
public BaseballPlayer( String name, String hometown, String state, int age, double height, String position) {
this.name = name;
this.hometown = hometown;
this.state = state;
this.age = age;
this.height = height;
this.position = position;
}
public void setName(String name) {
this.name = name;
}
public void setHometown(String hometown) {
this.hometown = hometown;
}
public void setState(String state) {
this.state = state;
}
public void setAge(int age) {
this.age = age;
}
public void setHeight(float height) {
this.height = height;
}
public void setPosition(String position) {
this.position = position;
}
public String toString() {
return String.format("Name: %s from %s, %s (height: %.1f)", name, hometown, state, height);
}
public BaseballPlayer(){}
// Turn a BaseballPlayer object into a String
public String getAsJSON() {
Map<String, Object> info = new HashMap<>();
info.put("name", name);
info.put("hometown", hometown);
info.put("state", state);
info.put("age", age);
info.put("height", height);
info.put("position", position);
try {
return mapper.writeValueAsString(info);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// Here's the method you ask for. I don't know what 'i' is supposed
// to do, since we're in the class for a single baseball player. You
// could create a class that contains a list of baseball players, but
// why not just use a List by itself, as I've done.
public String getBaseballPlayer(int i) {
return getAsJSON();
}
// Turn a list of BaseballPlayer objects into a list of Strings
public static List<String> playersToStrings(List<BaseballPlayer> players) {
List<String> r = new ArrayList<>();
for (BaseballPlayer player : players) {
r.add(player.getAsJSON());
}
return r;
}
// Turn a list of Strings into a list of BaseballPlayer objects
public static List<BaseballPlayer> stringsToPlayers(List<String> playerStrings) {
List<BaseballPlayer> r = new ArrayList<>();
for (String playerString : playerStrings) {
try {
BaseballPlayer player = mapper.readValue(playerString, BaseballPlayer.class);
r.add(player);
} catch (IOException e) {
e.printStackTrace();
}
}
return r;
}
public static void main(String... args) {
// Create a list of BaseballPlayer objects and print them
List<BaseballPlayer> players = new ArrayList<>();
players.add(new BaseballPlayer("Joe", "Boston", "MA", 25, 6.1, "First Base"));
players.add(new BaseballPlayer("Sam", "San Francisco", "CA", 28, 5.8, "Pitcher"));
players.add(new BaseballPlayer("Kelly", "Chicago", "IL", 32, 6.4, "Catcher"));
System.out.println(players);
// Convert the list to a list of Strings and print the list
List<String> playerStrings = playersToStrings(players);
System.out.println(playerStrings);
// Convert the Strings back into BaseballPlayer objects and print them
players = stringsToPlayers(playerStrings);
System.out.println(players);
}
}
and here's the resulting output:
[Name: Joe from Boston, MA (height: 6.1), Name: Sam from San Francisco, CA (height: 5.8), Name: Kelly from Chicago, IL (height: 6.4)]
[{"hometown":"Boston","name":"Joe","state":"MA","position":"First Base","age":25,"height":6.1}, {"hometown":"San Francisco","name":"Sam","state":"CA","position":"Pitcher","age":28,"height":5.8}, {"hometown":"Chicago","name":"Kelly","state":"IL","position":"Catcher","age":32,"height":6.4}]
[Name: Joe from Boston, MA (height: 6.1), Name: Sam from San Francisco, CA (height: 5.8), Name: Kelly from Chicago, IL (height: 6.4)]
Here, each player is turned into JSON individually. A few more lines of code, and you could turn an array of Baseball Player objects into a single String.
If this JSON-only solution isn't good enough for you, check out Gson. It can preserve all Java types. It just takes a bit more setup to describe how each of your objects should be turned into JSON and back.
I want to compare the content of two Lists, in particular a certain method of the custom object stored in both of these lists, let's call it #getID().
My approach is to have a method that tells me whether those two lists contain the same entries with the same IDs.
List<CustomObject> firstList;
List<CustomObject> secondList;
Looping through each entry in firstList, calling getID() on it and look if there is an object in secondList that returns the same value for getID().
What would be an efficient way to do this check? Preferably using Java 8 streams, they seam quite useful here.
If both lists are sorted you can do that:
public boolean equalsLists(List<YourClass> a, List<YourClass> b) {
if (a.size() != b.size()) {
return false;
}
for (int i = 0; i < a.size(); i++) {
if (!a.get(i).getId().equals(b.get(i).getId()) {
return false;
}
}
return true;
}
If you can sort the elements, sort them and apply the same algorithm shown before.
Otherwise the efficiency of your algorithm depends on many factors:
How often two lists can be equals
How long are the lists
If elements can be present more than one time in the list
If it is possible to apply a function to all the elements to know with reasonable safeness if two lists are not equals use this function before comparing element by element (for example, if you have strings of different size to check you can count the number of chars of each id of each list and if they are different you are sure that you can return false)
Assuming that both lists are sorted, you could use a comparator.
Comparator<List<CustomObject>> myComp = new Comparator<List<CustomObject>>() {
#Override
public int compare(List<CustomObject> customObjectList, List<CustomObject> t1) {
for (int i = 0; i < customObjectList.size(); i++) {
if (customObjectList.getId().equals(t1.getId())) {
// Do your logic here
}
}
}
};
myComp.compare(list1, list2);
This is the "Java" way of doing things. If the lists are mismatched in size, you will have to practice some sort of defensive programming. If they are not sorted, you can use Collections.sort prior to comparing these two lists.
One approach of getting repeated elements is using a Map as follows.
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public class SomeClass {
protected class Component {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Component(String id, String description) {
super();
this.id = id;
this.description = description;
}
String id;
String description;
#Override
public String toString() {
// TODO Auto-generated method stub
return "Id " + this.getId();
}
}
public static void main(String[] args) {
Component component1 = new SomeClass().new Component("1", "One");
Component component2 = new SomeClass().new Component("2", "One");
Component component3 = new SomeClass().new Component("1", "One");
Component component4 = new SomeClass().new Component("3", "Three");
Component component5 = new SomeClass().new Component("4", "Four");
List<Component> list1 = new ArrayList<Component>();
list1.add(component1);
list1.add(component2);
List<Component> list2 = new ArrayList<Component>();
list1.add(component1);
list1.add(component2);
list2.add(component3);
list2.add(component4);
list2.add(component5);
Map<String, Component> result = list2.stream().collect(Collectors.toMap(Component::getId, Function.identity()));
Set<Component> repeated = list1.stream().filter(component -> result.containsKey(component.getId()))
.collect(Collectors.toSet());
repeated.forEach(System.out::println);
}
}
Basically sorting could be done by following:
Collections.sort(List);
But my scenario is little bit different. I have a List which contains following objects.
Sample Code 1:
public class GetTraders {
private String getTraderLegalName;
private String businessName;
private Object status;
public GetTraders(String getTraderLegalName, String businessName, String status) {
this.getTraderLegalName=getTraderLegalName;
this.businessName=businessName;
this.status=status;
}
I have a class which will give value for above list as follow:
public Class getResult {
List<GetTraders> traders=new ArrayList<GetTraders>();
public void valueGivenByuser(String legal,String business,Object status)throws Exception {
GetTraders trade=new GetTraders(legal,business,status);
traders.add(trade); //Adding value to arrayList
}
}
The problem here is, once I added all values in traders arraylist I need to sort and display as output. I tried with collections.sort() but It shows compiler exception.
If you look closely to the Collections API, you will see that you have two options at your disposal:
1) make your GetTraders class implement the Comparable interface and call
public static <T extends Comparable<? super T>> void sort(List<T> list)
2) create a new Comparator for the GetTraders class and call
public static <T> void sort(List<T> list, Comparator<? super T> c)
The first solution is the easiest one but if you need to sort the GetTraders objects according to multiple criteria then the second one is the best choice.
As pointed out by #Vaseph, if you are using Java 8 instead, life suddenly becomes easier because all you need to do is:
traders.sort((GetTraders trade1, GetTraders trade2) -> {
return trade1.getBusinessName().compareTo(trade2.getBusinessName());
});
But if you are having troubles with the Comparable and Comparator interfaces, I would encourage you to first try the pre-Java-8 solutions before diving into the magic world of the functional interfaces.
For the sake of completeness, please also find below an example of each solution:
1) Comparable-based solution:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class GetTraders1 implements Comparable<GetTraders1> {
private String getTraderLegalName;
private String businessName;
private Object status;
public GetTraders1(String getTraderLegalName, String businessName, String status) {
this.getTraderLegalName=getTraderLegalName;
this.businessName=businessName;
this.status=status;
}
#Override
public int compareTo(GetTraders1 that) {
return this.getTraderLegalName.compareTo(that.getTraderLegalName);
}
#Override
public String toString() {
return "GetTraders [getTraderLegalName=" + getTraderLegalName + ", businessName=" + businessName + ", status=" + status + "]";
}
public static void main(String[] args) {
GetTraders1 getTraders1 = new GetTraders1("1", "bn", "status");
GetTraders1 getTraders2 = new GetTraders1("2", "bn", "status");
GetTraders1 getTraders3 = new GetTraders1("3", "bn", "status");
List<GetTraders1> list = new ArrayList<>();
list.add(getTraders3);
list.add(getTraders2);
list.add(getTraders1);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
2) Comparator-based solution
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class GetTraders2 {
private String getTraderLegalName;
private String businessName;
private Object status;
public GetTraders2(String getTraderLegalName, String businessName, String status) {
this.getTraderLegalName=getTraderLegalName;
this.businessName=businessName;
this.status=status;
}
#Override
public String toString() {
return "GetTraders [getTraderLegalName=" + getTraderLegalName + ", businessName=" + businessName + ", status=" + status + "]";
}
public static void main(String[] args) {
GetTraders2 getTraders1 = new GetTraders2("1", "bn", "status");
GetTraders2 getTraders2 = new GetTraders2("2", "bn", "status");
GetTraders2 getTraders3 = new GetTraders2("3", "bn", "status");
List<GetTraders2> list = new ArrayList<>();
list.add(getTraders3);
list.add(getTraders2);
list.add(getTraders1);
System.out.println(list);
Collections.sort(list, new Comparator<GetTraders2>() {
#Override
public int compare(GetTraders2 o1, GetTraders2 o2) {
return o1.getTraderLegalName.compareTo(o2.getTraderLegalName);
}
});
System.out.println(list);
}
}
here is another way to sort list elements based on businessName:
traders.sort((GetTraders trade1, GetTraders trade2) -> {
return trade1.getBusinessName().compareTo(trade2.getBusinessName());
});
This hasn't be proposed but here it is.
You should use Collections#sort with a Comparator
Collections.sort(traders, (x, y) -> x.getXXX().compareTo(y.getXXX()));
// XXX could be any String object's getter
Use Comparator to determine order.
Collections.sort(someList, comparator);