Find elements within array, by specific property with jxpath - java

What is wrong with the JXpath expression in the code below? The following code always throws this exception:
org.apache.commons.jxpath.JXPathNotFoundException: No value for xpath: countries[gdp=4]
However I expected the country Germany to be returned. Whats wrong here?
import org.apache.commons.jxpath.JXPathContext;
public class Test {
private final Country[] countries = {
new Country("US", 20),
new Country("China", 13),
new Country("Japan", 5),
new Country("Germany", 4),
new Country("UK", 3)};
public static void main(String[] args) {
Object result = JXPathContext.newContext(new Test()).getValue("countries[gdp=4]");
System.out.println(result);
}
public Country[] getCountries() {
return countries;
}
}
-
class Country{
private String name;
private int gdp;
public Country(String name, Integer gdp){
this.name=name;
this.gdp=gdp;
}
#Override
public String toString() {
return name;
}
public String getName() {
return name;
}
public int getGdp() {
return gdp;
}
}

I don't know enough about the jxpath lib you are using. But the xpath expression should be like this:
/countries/country[gdp=4]

It started to work after I replaced:
Object result = JXPathContext.newContext(new Test()).getValue("countries[gdp=4]");
By:
Iterator result = JXPathContext.newContext(new Test()).iterate("countries[gdp=4]");

Related

Filter an ArrayList of Objects using Java Streams to return an ArrayList of type String

I can't find an exact solution for this on SO. I have a Crowd class which consists of a Crowd object which is an arraylist of type People. People is a class with properties String name, Double bankBalance, Integer numberOfCarsOwned.
In my crowd class I have the following method whereby I seek to filter by names beginning with the letter P and return these an arraylist of type String:
public ArrayList<String> filterByLetterP(){
ArrayList<String> filteredNames = this.crowd.stream()
.filter(name -> name.getName().contains("P"));
return filteredNames;
}
My error is:
required type ArrayList<String> provided Stream<People>
Note: My solution must make use of streams. How can I correct my solution to get it to work?
Reference info below.
People class definition:
public class People {
private String name;
private Double bankBalance;
private Integer numberOfCarsOwned;
public People(String name, Double bankBalance, Integer numberOfCarsOwned) {
this.name = name;
this.bankBalance = bankBalance;
this.numberOfCarsOwned = numberOfCarsOwned;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getBankBalance() {
return bankBalance;
}
public void setBankBalance(Double bankBalance) {
this.bankBalance = bankBalance;
}
public Integer getNumberOfCarsOwned() {
return numberOfCarsOwned;
}
public void setNumberOfCarsOwned(Integer numberOfCarsOwned) {
this.numberOfCarsOwned = numberOfCarsOwned;
}
}
Crowdclass definition:
public class Crowd {
private ArrayList<People> crowd;
public Crowd() {
this.crowd = new ArrayList<>();
}
public ArrayList<People> getCrowd() {
return crowd;
}
public void setCrowd(ArrayList<People> crowd) {
this.crowd = crowd;
}
public void addPeopleToCrowd(People people){
this.crowd.add(people);
}
public ArrayList<String> filterByLetterP(){
ArrayList<String> filteredNames = this.crowd.stream()
.filter(name -> name.getName().contains("P"));
return filteredNames;
}
}
A couple of things needs to be addressed:
You should use String#startsWith instead of String#contains.
You have to map the Stream to People#name.
You have missed collecting the Stream.
Do it as shown below:
public List<String> filterByLetterP() {
List<String> filteredNames = this.crowd.stream()
.map(p -> p.getName())
.filter(s -> s.startsWith("P"))
.collect(Collectors.toList());
return filteredNames;
}
You should change your filter because it doesn't check names with beginning letter 'P':
public List<String> filterByLetterP(){
return this.crowd.stream()
.map(People::getName)
.filter(name -> name.charAt(0) == 'P')
.collect(Collectors.toList());
}

Mixed types in an Array gson [java]

I want to parse the following json. Everything works find except the args part. The gson looks like:
my.json
{
"daily":[
{
"type":"anystring",
"set":[0,0,"anystring"],
"args":[[0,1,"String"],[1,1,"String"]]
},
{
"type":"anystring",
"set":[0,0,"anystring"],
"args":[[0,0,"anystring"],1,2,3]
}
]}
My code looks like:
public class ReadJSON {
public static void main (String args[]) throws FileNotFoundException{
Gson gson = new Gson();
Daily data = gson.fromJson(new BufferedReader(new FileReader("my.json")), new TypeToken<Daily>() {}.getType());
System.out.println(data);
}
}
public class Daily {
public List<DailyRule> daily;
public List <DailyRule>getDaily(){
return daily;
}
#Override
public String toString() {
return daily.toString();
}
}
public class DailyRule {
public String type;
public List<String> set = new ArrayList<String>();
public List<String[]> args;
public String getType(){
return type;
}
public String getOp(){
return op;
}
public String getCond(){
return cond;
}
public List<String> getSet(){
return set;
}
public List<String[]> getArgs() {
return args;
}
#Override
public String toString() {
return type+" "+set.toString()+" "+args.toString();
}
}
it throws me an error like Expected BEGIN_ARRAY but was NUMBER at line...
Well I understand why the error is thrown but not how to fix it. I cannot change the json file (which would be probably the easiest solution). Are there easier solutions out there instead of using a serializer? How would I implement it? I hate being a noob :/ Thanks in advance
There exist multiple errors in your code. First
1) cond and op is not declared in DailyRule class.
String op;
String cond;
2) As you are inserting sometimes Array,other time integer to args, it must be List of args must be of type that can support any data type.
So
public List<Object> args;
So your daily route class must look like this.
import java.util.ArrayList;
import java.util.List;
public class DailyRule {
public String type;
public List<String> set = new ArrayList<String>();
public List<Object> args;
String op;
String cond;
public String getType(){
return type;
}
public String getOp(){
return op;
}
public String getCond(){
return cond;
}
public List<String> getSet(){
return set;
}
public List<Object> getArgs() {
return args;
}
#Override
public String toString() {
return type+" "+set.toString()+" "+args.toString();
}
}

Why Java Method Reference of instance method cannot be assigned to Consumer interface

Here is my Code :
public class SearchByLambda {
private Map<String,Consumer<Person>> searchCritertiaHolder = new HashMap<String,Consumer<Person>>();
private static final String AGED = "aged";
public SearchByLambda(){
searchCritertiaHolder.put(AGED, (Person p)-> {p.filterAgedPerson(p);} );
}
private Consumer<Person> getFilter(String personType){
return searchCritertiaHolder.get(personType);
}
public static void main(String[] args) {
SearchByLambda searchUsage = new SearchByLambda();
Person p = new Person(59,"shailesh");
Person p1 = new Person(58,"ganesh");
searchUsage.getFilter(AGED).accept(p);
searchUsage.getFilter(AGED).accept(p1);
Person.printAgedPersons();
}
}
class Person{
private static List<Person> agedPersons = new ArrayList<>();
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(int age,String name){
this.age = age;
this.name = name;
}
public void filterAgedPerson(Person person){
if(person.getAge() > 58){
agedPersons.add(person);
}
}
public static void printAgedPersons(){
for(Person person : agedPersons){
System.out.println(person.getName());
}
}
}
When I replace following Lambda expression
searchCritertiaHolder.put(AGED, (Person p)-> {p.filterAgedPerson(p);});
with
searchCritertiaHolder.put(AGED, Person::filterAgedPerson);
it gives me compilation error. I am using java 8 and and compiling through eclipse. Why is this so? Why cannot I assign method reference for instance method of any arbitrary object to consumer functional interface?
Your definition of filterAgedPerson takes a Person as an argument, even though it is not a static method. It doesn't need to, and it shouldn't if you want to use it as a Consumer<Person>. What you are ending up with is something compatible with BiConsumer<Person, Person>.
It might help to think of it this way: method references to non-static methods always take an "extra" argument which is used as this.
The easiest way for you to fix this with your current code structure is to modify the filterAgedPerson method to not take a Person as an argument
public void filterAgedPerson() {
if (this.getAge() > 58) {
agedPersons.add(person);
}
}
As an aside, you might want to also consider making your filters Predicate<Person> instead of Consumer<Person> and moving the results handling elsewhere. This will give you more flexibility as things get more complicated.

Is there any default method for ENUM? [duplicate]

What is the best way to use the values stored in an Enum as String literals?
For example:
public enum Modes {
some-really-long-string,
mode1,
mode2,
mode3
}
Then later I could use Mode.mode1 to return its string representation as mode1. Without having to keep calling Mode.mode1.toString().
You can't. I think you have FOUR options here. All four offer a solution but with a slightly different approach...
Option One: use the built-in name() on an enum. This is perfectly fine if you don't need any special naming format.
String name = Modes.mode1.name(); // Returns the name of this enum constant, exactly as declared in its enum declaration.
Option Two: add overriding properties to your enums if you want more control
public enum Modes {
mode1 ("Fancy Mode 1"),
mode2 ("Fancy Mode 2"),
mode3 ("Fancy Mode 3");
private final String name;
private Modes(String s) {
name = s;
}
public boolean equalsName(String otherName) {
// (otherName == null) check is not needed because name.equals(null) returns false
return name.equals(otherName);
}
public String toString() {
return this.name;
}
}
Option Three: use static finals instead of enums:
public final class Modes {
public static final String MODE_1 = "Fancy Mode 1";
public static final String MODE_2 = "Fancy Mode 2";
public static final String MODE_3 = "Fancy Mode 3";
private Modes() { }
}
Option Four: interfaces have every field public, static and final:
public interface Modes {
String MODE_1 = "Fancy Mode 1";
String MODE_2 = "Fancy Mode 2";
String MODE_3 = "Fancy Mode 3";
}
Every enum has both a name() and a valueOf(String) method. The former returns the string name of the enum, and the latter gives the enum value whose name is the string. Is this like what you're looking for?
String name = Modes.mode1.name();
Modes mode = Modes.valueOf(name);
There's also a static valueOf(Class, String) on Enum itself, so you could also use:
Modes mode = Enum.valueOf(Modes.class, name);
You could override the toString() method for each enum value.
Example:
public enum Country {
DE {
#Override
public String toString() {
return "Germany";
}
},
IT {
#Override
public String toString() {
return "Italy";
}
},
US {
#Override
public String toString() {
return "United States";
}
}
}
Usage:
public static void main(String[] args) {
System.out.println(Country.DE); // Germany
System.out.println(Country.IT); // Italy
System.out.println(Country.US); // United States
}
As Benny Neugebauer mentions, you could overwrite the toString(). However instead overwriting the toString for each enum field I like more something like this:
public enum Country{
SPAIN("EspaƱa"),
ITALY("Italia"),
PORTUGAL("Portugal");
private String value;
Country(final String value) {
this.value = value;
}
public String getValue() {
return value;
}
#Override
public String toString() {
return this.getValue();
}
}
You could also add a static method to retrieve all the fields, to print them all, etc.
Simply call getValue to obtain the string associated to each Enum item
mode1.name() or String.valueOf(mode1). It doesn't get better than that, I'm afraid
public enum Modes {
MODE1("Mode1"),
MODE2("Mode2"),
MODE3("Mode3");
private String value;
public String getValue() {
return value;
}
private Modes(String value) {
this.value = value;
}
}
you can make a call like below wherever you want to get the value as a string from the enum.
Modes.MODE1.getvalue();
This will return "Mode1" as a String.
For my enums I don't really like to think of them being allocated with 1 String each. This is how I implement a toString() method on enums.
enum Animal
{
DOG, CAT, BIRD;
public String toString(){
switch (this) {
case DOG: return "Dog";
case CAT: return "Cat";
case BIRD: return "Bird";
}
return null;
}
}
You can use Mode.mode1.name() however you often don't need to do this.
Mode mode =
System.out.println("The mode is "+mode);
As far as I know, the only way to get the name would be
Mode.mode1.name();
If you really need it this way, however, you could do:
public enum Modes {
mode1 ("Mode1"),
mode2 ("Mode2"),
mode3 ("Mode3");
private String name;
private Modes(String s) {
name = s;
}
}
my solution for your problem!
import java.util.HashMap;
import java.util.Map;
public enum MapEnumSample {
Mustang("One of the fastest cars in the world!"),
Mercedes("One of the most beautiful cars in the world!"),
Ferrari("Ferrari or Mercedes, which one is the best?");
private final String description;
private static Map<String, String> enumMap;
private MapEnumSample(String description) {
this.description = description;
}
public String getEnumValue() {
return description;
}
public static String getEnumKey(String name) {
if (enumMap == null) {
initializeMap();
}
return enumMap.get(name);
}
private static Map<String, String> initializeMap() {
enumMap = new HashMap<String, String>();
for (MapEnumSample access : MapEnumSample.values()) {
enumMap.put(access.getEnumValue(), access.toString());
}
return enumMap;
}
public static void main(String[] args) {
// getting value from Description
System.out.println(MapEnumSample.getEnumKey("One of the fastest cars in the world!"));
// getting value from Constant
System.out.println(MapEnumSample.Mustang.getEnumValue());
System.out.println(MapEnumSample.getEnumKey("One of the most beautiful cars in the world!"));
System.out.println(MapEnumSample.Mercedes.getEnumValue());
// doesnt exist in Enum
System.out.println("Mustang or Mercedes, which one is the best?");
System.out.println(MapEnumSample.getEnumKey("Mustang or Mercedes, which one is the best?") == null ? "I don't know!" : "I believe that "
+ MapEnumSample.getEnumKey("Ferrari or Mustang, which one is the best?") + " is the best!.");
// exists in Enum
System.out.println("Ferrari or Mercedes, wich one is the best?");
System.out.println(MapEnumSample.getEnumKey("Ferrari or Mercedes, which one is the best?") == null ? "I don't know!" : "I believe that "
+ MapEnumSample.getEnumKey("Ferrari or Mercedes, which one is the best?") + " is the best!");
}
}
You can simply use:
""+ Modes.mode1
public enum Environment
{
PROD("https://prod.domain.com:1088/"),
SIT("https://sit.domain.com:2019/"),
CIT("https://cit.domain.com:8080/"),
DEV("https://dev.domain.com:21323/");
private String url;
Environment(String envUrl) {
this.url = envUrl;
}
public String getUrl() {
return url;
}
}
String prodUrl = Environment.PROD.getUrl();
It will print:
https://prod.domain.com:1088/
This design for enum string constants works in most of the cases.
Enum is just a little bit special class. Enums can store additional fields, implement methods etc. For example
public enum Modes {
mode1('a'),
mode2('b'),
mode3('c'),
;
char c;
private Modes(char c) {
this.c = c;
}
public char character() {
return c;
}
}
Now you can say:
System.out.println(Modes.mode1.character())
and see output:
a
package com.common.test;
public enum Days {
monday(1,"Monday"),tuesday(2,"Tuesday"),wednesday(3,"Wednesday"),
thrusday(4,"Thrusday"),friday(5,"Friday"),saturday(6,"Saturday"),sunday(7,"Sunday");
private int id;
private String desc;
Days(int id,String desc){
this.id=id;
this.desc=desc;
}
public static String getDay(int id){
for (Days day : Days.values()) {
if (day.getId() == id) {
return day.getDesc();
}
}
return null;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
};
This method should work with any enum:
public enum MyEnum {
VALUE1,
VALUE2,
VALUE3;
public int getValue() {
return this.ordinal();
}
public static DataType forValue(int value) {
return values()[value];
}
public String toString() {
return forValue(getValue()).name();
}
}
i found this one is more easy for preventing type error:
public enum Modes {
some-really-long-string,
mode1,
mode2,
mode3;
String str;
Modes(){
this.str = super.name();
}
#Override
#NonNull
public String toString() {
return str;
}
however - this may work when you need to use a String on a log/println or whenever java compiles the toString() method automatically, but on a code line like this ->
// sample method that require (string,value)
intent.putExtra(Modes.mode1 ,shareElement.getMode()); // java error
// first argument enum does not return value
instead as mentioned above you will still have to extend the enum and use .name() in those cases like this:
intent.putExtra(Modes.mode1.name() ,shareElement.getMode());
after many tries I have come with this solution
public static enum Operation {
Addition, Subtraction, Multiplication, Division,;
public String getUserFriendlyString() {
if (this==Addition) {
return " + ";
} else if (this==Subtraction) {
return " - ";
} else if (this==Multiplication) {
return " * ";
} else if (this==Division) {
return " / ";
}
return "undefined";
}
}
You can try this:
public enum Modes {
some-really-long-string,
mode1,
mode2,
mode3;
public String toString(){
switch(this) {
case some-really-long-string:
return "some-really-long-string";
case mode2:
return "mode2";
default: return "undefined";
}
}
}
use mode1.name() or String.valueOf(Modes.mode1)

UML class diagram implementation Address-Addressbook

I have 2 class diagrams, class Address
+forename
+surename
+street
+houseno
+code
+state
+toString
second Addressbook
insert(address: Address)
toString()
searchSurename (surename: string): Address[*]
+searchForename(forename: string): Address[*]
i implemented address:
public class Address {
public static String forename;
public static String surename;
public static String street;
public static int houseno;
public static int code;
public static String state;
public String toString(){
return this.forename + this.surename + this.street + this.houseno + this.code + this.state;
}
How can I implement Addressbook as easy as possible?
EDIT:
public class addressbook{
private static ArrayList<Address> book;
public addressbook(){
book = new ArrayList<Address>();
}
}
EDIT QUESTION:
Am I allowed to add new methods or attributes in a implementation outside the ones that we use in our class diagrams?
EDIT 2:
First try implementing method searchSurename with an ArrayList:
public static String searchSurename(String surename){
boolean exist = false;
if(this.addresses.isEmpty()){
return null;
}
for(int i=0;i<this.addresses.size();i++) {
if(this.addresses.get(i).getSurename() == surename) {
exist=true;
break;
}
if(exist) {
return this.addresses.get(surename);
} else {
return this.addresses.get(surename);
}
}
// return ?!?
}
The Program give me Errors at "this" at any line, maybe a mistake but I cant tell! It Looks a Little bit too difficult, I don't find any implementations where searching through a list is simple.
You could implement it in a way like this. Look at the api for arrayList for using its methods.
public class Adressbook {
List<Adress> adresses = new ArrayList<Adress>();
public Adressbook(){
adresses = new arraylist<Adress>();
}
public insert (Adress adress){
adresses.add(adress)
}
public searchSurename(String Surename){
}
public searchForename(String forename){
}
public String toString(){
}
ArrayList api:
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
To have unique address use set collection interface
public class Adressbook {
....
private Set<Adress> adresses = null;
public Adressbook(){
adresses = new HashSet<Adress>();
}
public void add(Adress adress){
adresses.add(adress)
}
...
}

Categories