Querying on Java Object's without Database - java

Note: Little long question. I'm going to give a bounty for best answer.
What I'm trying to do is querying on Object. Here is the details. I have a file called employee.txt. So I parsed it and kept in the list
public static List<Employee> employeeList = new LinkedList<>();
Then here is my logic to query.
Take the query from user, and then parse it. The below is the logic to query through the list.
For ex: here is the query
select * from Employee where id > 10
My codes for that
String valueToCompare = split[5]; //10
EmployeeCriteria criteria = new EmployeeCriteria(
isId, isName, isSalary, expression,
valueToCompare);
result = EmployeeData.findAll(
EmployeeData.employeeList, criteria);
Here is the findAll method
public static List<Employee> findAll(List<Employee> coll,
ISearch<Employee> chk) {
List<Employee> l = new LinkedList<Employee>();
for (Employee obj : coll) {
if (chk.search(new Employee(obj)))
l.add(obj);
}
return l;
}
And here is my search method
/**
* Based on the type provided and for given expression it check against the
* given value
*/
#Override
public boolean search(Employee obj) {
if (expression.equals(EQUAL)) {
if (isId()) {
if (obj.getId() == Long.parseLong(valueToCompare)) {
return true;
}
} else if (isName()) {
if (obj.getName().equals(valueToCompare)) {
return true;
}
} else if (isSalary()) {
if (obj.getSalary() == Long.parseLong(valueToCompare)) {
return true;
}
} else {
System.err.println(UserMessage.INVALIDCOLUMN_NAME);
}
} else if (expression.equals(NOT_EQUAL)) {
if (isId()) {
if (!(obj.getId() == Long.parseLong(valueToCompare))) {
return true;
}
} else if (isName()) {
if (!(obj.getName().equals(valueToCompare))) {
return true;
}
} else if (isSalary()) {
if (!(obj.getSalary() == Long.parseLong(valueToCompare))) {
return true;
}
} else {
System.err.println(UserMessage.INVALIDCOLUMN_NAME);
}
} else if (expression.equals(GREATER)) {
if (isId()) {
if ((obj.getId() > Long.parseLong(valueToCompare))) {
return true;
}
} else if (isSalary()) {
if ((obj.getSalary() > Long.parseLong(valueToCompare))) {
return true;
}
} else {
System.err.println(UserMessage.INVALIDCOLUMN_NAME);
}
} else if (expression.equals(LESSER)) {
if (isId()) {
if ((obj.getId() < Long.parseLong(valueToCompare))) {
return true;
}
} else if (isSalary()) {
if ((obj.getSalary() < Long.parseLong(valueToCompare))) {
return true;
}
} else {
System.err.println(UserMessage.INVALID_IDENTIFIER);
}
}
return false;
}
Let me know if you want to see any other codes.
I just want to know,
In the first place LinkedList is correct data structure to use ? Is this performs well ?? Any enhancements to perform well ?
Any better way to achieve this ?
here are few example queries:
select * where ID > 100
select * where Name != Ramesh
select * where Salary < 500000
select Name order by Name
select ID
Thanks for any help. Bounty will be offered after 2 days. I can't do that now.
Note2: This is a test to check my data manage skills and I cannot use any database.

No, this does not perform well at all. You are searching through N employees every time. So if you have 1 million employees, you will search all 1 million employees before returning the correct employee. Even worst, if it doesn't exist, you will have to search exhaustibly before you can know if it exists.
Is this for use in production? If so then just use SQLite or some other simple database. You want to write once and read multiple times with indexes. I cannot stress enough that what you are writing will have bugs and instead you should use something that was already tested.
Assuming this is not for production and you are just having fun, then you want to emulate what databases do in real life. They create indexes. Indexes are usually best described as Map<String, List<Employee>>.
The idea is that initially reading the data from disk is expensive. But you read it once. For each dimension, Name, Salary, ID, etc... you want create separate indexes.
So let's say you were creating an index of all employees by ID. You would want to do something like:
Map<String, Employee> employeesById = new HashMap<>();
for(Employee e : employees) {
employeesById.put(e.getId(), e);
}
The above assumes that employee ids are unique. If they are not then you would need create a List<Employee>. For example for index by name:
Map<String,List<Employee>> employeesByName = new HashMap<>();
for(Employee e : employees) {
employeesByName.get(e.getName()).add(e); // Make sure to create the array if it doesn't exist
}
So now, for reading, let's say you get SELECT * FROM employees where id = 123; you can simply just return employeesById.get("123").
This solution is O(1). As the file gets bigger, you will not have any performance loss. This is probably the fastest solution.

To add onto Amir's answer, you can also use a TreeMap<> instead of a HashMap<>. Databases normally don't create indexes as hash maps but as balanced binary trees, which is what Java's TreeMap<> class is.
http://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html
HashMap<> has O(1) lookup on keys, but is exact match on key only. TreeMap<> has O(log n) lookup on keys, but allows ranged lookups higherKey, lowerKey) and map partitioning on key range (subMap).
The problem of duplicates can either be solved by not allowing them (unique key) or storing values in a list and linear search on the subset (non-unique key).

Assuming you are not interested in any of the in-memory database solution and using Java 8,
You should convert all your conditions to predicate and apply them on the stream . This will take advantage of Java 8's parallelism feature http://blog.takipi.com/new-parallelism-apis-in-java-8-behind-the-glitz-and-glamour/
So in short your code can be much cleaner and faster
public static Predicate<Employee> isSalaryGreaterThan(Integer salary) {
return p -> p.getSalary() > salary;
}
Predicate predicate1 = isSalaryGreaterThan(50000)
employeeList.stream().filter(predicate1).filter(predicate2)...collect(Collectors.<Employee>toList())

Related

Check List has only one non null element and retrieve it using Java 8

How to check whether the list has only one non-null element and if so retrieve the same using java 8 or Streams?
One of my method return list of objects which needs to check whether the returned list contains only one non null object, If so it creates a map as defined below else, needs to log an error as below.
`public void myMethod() {
List<MyClass> tst = getAll();
if(!tst.isEmpty() ) {
if( tst.size() == 1) {
if(tst.get(0)!= null) {
MyClass class1 = tst.get(0);
Map<Integer,MyClass> m =
Stream.of(class1).collect(Collectors.toMap(MyClass:: getId,
Function.identity()));
}
}
else {
LOGGER.error("Multiple object found - {} object", tst.size());
}
}`
I'm looking for a way to write in a clean and standard format as I have three If conditions
Something like that should do the trick but it's not using streams. If you really need to use streams say so and I'll give it a try with it :)
int notNullCount = 0;
Object myNotNullElement;
for (Object element : myArray){
if (notNullCount > 1){
//Throw exception or do whaterver you need to do to signal this
break;
}
if (element != null){
myNotNullElement = element;
notNullCount++;
}
}

How to check all members of an array

I am writing a text-based survival simulator that uses an array of Entitys. The Entity class contains data about each entity, such as energy, hydration, and morale. I'm starting to wrap up the project but I have a problem. In order to write a checkStatus() method, I need to have an if statement that checks for Entity[].isAlive on all entities, even if I don't know how long the array is. In short, how can I use an if statement to check for the value of all members of an array? I know I will probably have to use a for loop to iteratively check the members, with the array.getLength. So far I can only check variables in single classes. I have seen similar questions but they don't quite get what I'm looking for.
P.S. I'm using basic Java, with no frameworks or libraries.
Pseudo-code that demonstrates what I'm looking for
if Entity[ALL-MEMBERS].isAlive {
gameOver = true;
}
Java 6, 7, and 8:
public boolean areAllAlive(Entity[] entities) {
if(entities == null || entities.length == 0) {
return false; //?
}
for(Entity e : entities) {
if(!e.isAlive()) {
return false;
}
}
return true;
}
Java 8, using streams/functions:
public boolean areAllAlive(Entity[] entities) {
if(entities == null || entities.length == 0) {
return false; //?
}
return Arrays.stream(entities).allMatch(e -> e.isAlive());
}
First, since you probably don't know the number of Entities you are going to use before hand an ArrayList is probably a better choice. Then yes, you should use an enhanced for loop:
List<Entity> list = new ArrayList<>();
public void addEntities(){
//add Entities here
}
public boolean ifAlive(){
for (Entity e: list){
if (!e.isAlive()){
return false;
}
}
return true;
}
or something like that.
Assuming array is your entity's array, try this.:
for (int i = 0; i < array.length; i++) {
Entity entity = array[i];
if (entity.isAlive) {
gameOver = true;
//your code here
}
}

performace issue with the code ,exponential working

I have two lists of type object with data , the first one is principal entity and the second is dependent entity.
In addition I have key table that relate between the principal and depended entity objects.
In the first for statement I get one instance of type object and then I go and loop on every instance of the second entity and trying to find
Match between them (i think exponential problem…) ,if match is find update the principal entity with the reference object .
The following code is working but I check it from performance perspective and it's not working in efficient way.
Do you have an idea/tips how to improve this code from perforce aspect.
In the JVM monitor I found that EntityDataCreator.getInstanceValue have a problem.
This is the method start
// start with the principal entity
for (Object principalEntityInstance : principalEntityInstances) {
List<Object> genObject = null;
Object refObject = createRefObj(dependentMultiplicity);
// check entries in dependent entity
for (Object dependentEntityInstance : toEntityInstances) {
boolean matches = true;
for (String[] prop : propertiesMappings) {
// Get properties related keys
String fromProp = prop[0];
String toProp = prop[1];
Object fromValue = EntityDataCreator.getInstanceValue(fromProp, principalEntityInstance);
Object toValue = EntityDataCreator.getInstanceValue(toProp, dependentEntityInstance);
if (fromValue != null && toValue != null) {
if (!fromValue.equals(toValue)) {
matches = false;
break;
}
}
}
if (matches) {
// all properties match
if (refObject instanceof List) {
genObject = (List<Object>) refObject;
genObject.add(dependentEntityInstance);
refObject = genObject;
} else {
refObject = dependentEntityInstance;
break;
}
}
}
if (refObject != null) {
EntityDataCreator.createMemberValue(principalEntityInstance, navigationPropName, refObject);
}
}
public static Object getInstanceValue(String Property, Object EntityInstance) throws NoSuchFieldException,
IllegalAccessException {
Class<? extends Object> EntityObj = EntityInstance.getClass();
Field Field = EntityObj.getDeclaredField(Property);
Field.setAccessible(true);
Object Value = Field.get(EntityInstance);
Field.setAccessible(false);
return Value;
}
my guess would be your best bet is to go through both lists once, prepare all data that you need in hashtables, then do one iteration. this way, your problem becomes N+M instead of N*M
edit
Map<String,List<Object>> principalMap = new HashMap<String,List<Object>>();
for (Object principalEntityInstance : principalEntityInstances) {
List<String> keys = getKeysFor(principalEntityInstance);
for(String key : keys) {
List<Object> l = principalMap.get(key);
if(l==null) {
l = new ArrayList<Object>();
principalMap.put(key,l);
}
l.add(principalEntityInstance);
}
}
the do the same for dependentEntityInstance - this way, your searches will be much faster.
I might be misunderstanding your question, but I would suggest defining an equals method for your entities and a hashing method for them, so that you can leverage all the goodness that java already has for searching and matching entities already.
When at all possible rely on Java's infrastructure I think, Sun/Oracle spent a long time making it really fast.

Java list : get next or previous element from an identifier

I want to navigate into a list by identifier.
1- I manage/create a list.
2- I create function to get next item of a identifier element from my list
Can you help me to fix this code?
Prepare the list
List<String> myList = new ArrayList<String>();
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("4");
myList.add("5");
public String function getNext(String uid) {
if (myList.indexOf(uid).hasNext()) {
return myList.indexOf(uid).nextElement();
}
return "";
}
public String function getPrevious(String uid) {
return myList.indexOf(uid).hasPrevious() ? myList.indexOf(uid).previousElement() : "";
}
You could use an index to lookup your String which is faster and simpler however to implement the functions as you have them.
public String getNext(String uid) {
int idx = myList.indexOf(uid);
if (idx < 0 || idx+1 == myList.size()) return "";
return myList.get(idx + 1);
}
public String getPrevious(String uid) {
int idx = myList.indexOf(uid);
if (idx <= 0) return "";
return myList.get(idx - 1);
}
Using a List.get(i) is O(1) which makes keeping the index the fastest option. List.indexOf(String) is O(n). Using a NavigatbleSet might appear attractive as it is O(log n), however the cost of creating an object is so high that the collection has to be fairly large before you would see a benefit. (In which case you would use the first option)
If your elements are not repeated, what you need is a NavigableSet:
http://download.oracle.com/javase/6/docs/api/java/util/NavigableSet.html
The methods higher and lower are what you are looking for.
Lists don't have a nextElement() method. indexOf returns the integer index of the item. You could simply add (or subtract) one to get the next (or previous) item:
public String function getNext(String uid) {
var index = myList.indexOf(uid);
if (index > -1) {
try {
return myList.get(i+1);
} catch ( IndexOutOfBoundsException e) {
// Ignore
}
}
return ""; // consider returning `null`. It's usually a better choice.
}
However looking up an object with indexOf on ArrayList is a very slow process, because it has to check every single entry. There are better ways to this, but that depends on what you are actually trying to achieve.

Search an attribute inside a Vector on Java

I've a Vector of objects, and have to search inside for a random attribute of those objects (For example, a Plane class, a Vector containing Plane; and I've to search sometimes for destination, and others to pilotName).
I know I can traverse the Vector using an Iterator, but I've got stuck at how do I change the comparison made between a String and the attribute on the object. I thought of using switch, but a another opinion would be cool.
Update 1:
The code I've written is something like this (Java n00b alert!):
public int search(String whatSearch, String query){
int place = -1;
boolean found = false;
for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {
Plane temp = (Plane) iteraPlane.next();
/* Here is where I have to search for one of many attributes (delimited by whatSearch */
}
return place;
}
Seems I've to stick to linear search (and that's a price I've able to pay). Anyway, I was thinking if Java had something like variable variable name (ouch!)
I assume that your problem is that you want to have a method that searches for a result based on some property of the collection type. Java is weak on this because it is best expressed in a language which has closures. What you need is something like:
public interface Predicate<T> {
public boolean evaluate(T t);
}
And then your search method looks like:
public static <T> T findFirst(List<T> l, Predicate<T> p) { //use List, not Vector
for (T t : l) { if (p.evaluate(t)) return t; }
return null;
}
Then anyone can use this general-purpose search method. For example, to search for an number in a vector of Integers:
List<Integer> is = ...
findFirst(is, new Predicate<Integer> {
public boolean evaluate(Integer i) { return i % 2 == 0; }
});
But you could implement the predicate in any way you want; for any arbitrary search
Use Collections.binarySearch and provide a Comparator.
EDIT: This assumes that the Vector is sorted. Otherwise, one has to do a linear search.
the equals() method is the best option. For these iterations you could do something like this:
for (Plane plane: planes) {
if ("JFK".equals(plane.getDestination())) {
// do your work in here;
}
}
or you could override the equals() method within Plane to see if the String passed in matches your destination (or pilot). this will allow you to use the indexOf(Object) and indexOf(Object, index) methods on Vector to return you the index(es) of the object(s). Once you have that, you could use Vector.get(index) to return to Object for you.
in Plane.java:
public boolean equals(Object o) {
return o.equals(getDestination()) ||
o.equals(getPilot()) ||
super.equals(o);
}
there is more work to be done with this option, as you will need to override hashCode() as well (see documentation).
See #oxbow_lakes above -- I think what you want isn't to pass a String as whatSearch, it's to pass a little snippet of code that knows how to get the property you're interested in. For a less general version:
public static interface PlaneMatcher {
boolean matches(Plane plane, String query);
}
public int search(PlaneMatcher matcher, String query){
int place = -1;
boolean found = false;
for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {
Plane temp = (Plane) iteraPlane.next();
if (matcher.matches(temp, query) {
found = true;
}
place++;
}
return place;
}
...
// example
int pilotNameIndex = search(new PlaneMatcher() {
boolean matches(Plane plane, String query) {
// note: assumes query non-null; you probably want to check that earlier
return query.equals(plane.getPilotName());
}
}, "Orville Wright");
(By the way, if it's the index you're interested in rather than the Plane itself, I wouldn't bother with an Iterator -- just use an old-fashioned for (int i = 0; i < planes.size(); i++) loop, and when you have a match, return i.)
Now, the tricky bit here is if what you have to search for is really identified by arbitrary strings at run-time. If that's the case, I can suggest two alternatives:
Don't store these values as object fields -- plane.pilotName, plane.destination -- at all. Just have a Map<String, String> (or better yet, a Map<Field, String> where Field is an Enum of all the valid fields) called something like plane.metadata.
Store them as object fields, but prepopulate a map from the field names to PlaneMatcher instances as described above.
For instance:
private static final Map<String, PlaneMatcher> MATCHERS = Collections.unmodifiableMap(new HashMap<String, PlaneMatcher>() {{
put("pilotName", new PlaneMatcher() {
boolean matches(Plane plane, String query) {
return query.equals(plane.getPilotName());
});
...
put("destination", new PlaneMatcher() {
boolean matches(Plane plane, String query) {
return query.equals(plane.getDestination());
});
}}
...
public int search(String whatSearch, String query){
PlaneMatcher matcher = MATCHERS.get(whatSearch);
int place = -1;
boolean found = false;
for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {
Plane temp = (Plane) iteraPlane.next();
if (matcher.matches(temp, query) {
found = true;
}
place++;
}
return place;
}
Oh, and you might be tempted to use reflection. Don't. :)
A simple way is to pass a comparison function to your search routine. Or, if you need more speed, use generics.

Categories