I have a class Object1 which has a list of longs called tags. I have another list of longs called tagsToSearch. How can I construct a query using CQEngine that is the following:
Select * from Object1 Where tags in (tagsToSearch)
If anyone knows how this would look using CQEngine please let me know.
This should do the trick:
package com.googlecode.cqengine;
import com.googlecode.cqengine.attribute.*;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.query.option.QueryOptions;
import com.googlecode.cqengine.query.parser.sql.SQLParser;
import java.util.*;
import static com.googlecode.cqengine.codegen.AttributeBytecodeGenerator.*;
import static com.googlecode.cqengine.query.QueryFactory.*;
import static java.util.Arrays.asList;
public class TagsExample {
static class MyObject {
final String name;
final List<Long> tags;
public MyObject(String name, List<Long> tags) {
this.name = name;
this.tags = tags;
}
static final Attribute<MyObject, Long> TAGS = new MultiValueAttribute<MyObject, Long>("tags") {
public Iterable<Long> getValues(MyObject object, QueryOptions queryOptions) { return object.tags; }
};
}
public static void main(String[] args) {
IndexedCollection<MyObject> collection = new ConcurrentIndexedCollection<>();
collection.add(new MyObject("foo", asList(1L, 2L, 3L)));
collection.add(new MyObject("bar", asList(4L, 5L, 6L)));
collection.add(new MyObject("baz", asList(7L, 8L, 9L)));
// Search via a programmatic query...
Query<MyObject> nativeQuery = in(MyObject.TAGS, asList(3L, 9L));
collection.retrieve(nativeQuery)
.forEach(object -> System.out.println(object.name));
// ..prints: foo, baz
// Search via an SQL query...
String sqlQuery = "SELECT * FROM collection WHERE tags IN (3, 9)";
SQLParser<MyObject> parser = SQLParser.forPojoWithAttributes(MyObject.class, createAttributes(MyObject.class));
parser.retrieve(collection, sqlQuery)
.forEach(object -> System.out.println(object.name));
// ..prints: foo, baz
}
}
Related
We are creating CSV files from DTO classes, using reflection to get the names of all the column names. ClassName.class.getDeclaredFields() gives us array of all column names.
We have a use case where, we have classes with composition relation, like below:
public class Book {
private String title;
private Author author;
}
public class Author {
private String name;
private Integer age:
}
Here Book is the root class, i.e., final CSV will be named books.csv
With Book.class.getDeclaredFields(), we only get field names title and author, but we also want field names from Author class (name and age), is there a way to get those?
Notes:
It is far from optimal.
Circular reference problem is not considered.
Given your model it would return a list with this elements:
title
author.name
author.age
Usage:
ClassMetadataService cms = new ClassMetadataService();
List<String> properties = cms.getProperties(Book.class);
Class definition:
package io.metadata;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ClassMetadataService {
public List<String> getProperties(Class clazz) {
List<String> properties = new ArrayList<>();
this.collectProperties(new ArrayList<>(), clazz, properties);
return properties;
}
private void collectProperties(List<String> pathNodes, Class clazz, List<String> properties) {
for (Field field : clazz.getDeclaredFields()) {
List<String> localPathNodes = new ArrayList<>(pathNodes);
localPathNodes.add(field.getName());
if (clazz.isPrimitive() || isJavaClass(field.getType())) {
properties.add(localPathNodes.stream().collect(Collectors.joining(".")));
} else {
collectProperties(localPathNodes, field.getType(), properties);
}
}
}
private Boolean isJavaClass(Class clazz) {
List<Class> javaClass = Arrays.asList(
// ....
Boolean.class,
Byte.class,
Short.class,
Integer.class,
Long.class,
Float.class,
Double.class,
BigDecimal.class,
BigInteger.class,
Character.class,
String.class,
LocalDate.class,
LocalDateTime.class
// ....
);
return javaClass.stream().anyMatch(jc -> jc.equals(clazz));
}
}
I have a map in java which has String as Key and an integer list as value. My query returns the below set
"Day:1, Day:2, Day:3, Month:1, Year:15, Year:20, Year:25"
Meaning, I have keys and different values for each keys in random.. I am expecting an output of a map which has unique key and corresponding list of int in values as seen below:
{
"day": [1,2,3],
"Month": [1],
"year": [15,20,25]
}
Kindly help
public static void main(String[] args){
String input = "Day:1, Day:2, Day:3, Month:1, Year:15, Year:20, Year:25";
List<String> list = Arrays.asList(input.split(","));
JSONObject jsonObject = new JSONObject();
for (String val : list) {
String[] splitedValues = val.split(":");
if(jsonObject.has(splitedValues[0].trim())) {
jsonObject.getJSONArray(splitedValues[0].trim()).put(Integer.valueOf(splitedValues[1]));
}else {
List<Integer> integers = new ArrayList<Integer>();
integers.add(Integer.valueOf(splitedValues[1]));
jsonObject.put(splitedValues[0].trim(), integers);
}
}
System.out.println(jsonObject);
}
output
{"Month":[1],"Year":[15,20,25],"Day":[1,2,3]}
Please find below code. I have created an inner class to map type and value and then collected it by grouping the type.
import java.util.Map;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
public class StringToMap {
public static void main(String[] args) {
String queryOutput = "Day:1, Day:2, Day:3, Month:1, Year:15, Year:20, Year:25";
System.out.println(groupByTypeAndAddValuesToList(queryOutput));
}
private static Map<String, List<Integer>> groupByTypeAndAddValuesToList(String queryOutput) {
final String[] split = queryOutput.split(",");
return Arrays.stream(split).map(s -> {
final String trimmed = s.trim();
final String[] splitByColon = trimmed.split(":");
return new TypeValues(splitByColon[0], Integer.parseInt(splitByColon[1]));
}).collect(groupingBy(TypeValues::getType, Collectors.mapping(TypeValues::getValue, toList())));
}
private static class TypeValues {
private final String type;
private final Integer value;
public TypeValues(String type, Integer value) {
this.type = type;
this.value = value;
}
public String getType() {
return type;
}
public Integer getValue() {
return value;
}
}
}
I need to sort a collection with multiple conditions. But, in between these conditions I need to modify the stream data.
Customer.class
import java.math.BigDecimal;
import java.util.Date;
public class Customer {
private int id;
private String name;
private long quantity;
private BigDecimal cost;
private Date lastPurchasedDate;
public Customer(int id, String name, long quantity, BigDecimal cost) {
this.id = id;
this.name = name;
this.quantity = quantity;
this.cost = cost;
}
// setters & getters are omitted for brevity.
}
Main.class
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class Main {
public static void main(String[] args) {
List<Customer> customers = Arrays.asList(new Customer(1, "A", 10, BigDecimal.valueOf(673.89)),new Customer(2, "B", 10, BigDecimal.valueOf(673.89)));
getCustomer(customers).ifPresent(c -> System.out.println(c.getId()));
}
private static Optional<Customer> getCustomer(List<Customer> customers) {
// #formatter:off
return customers.stream()
.max(
Comparator.comparing(Customer::getQuantity)
.thenComparing(Customer::getCost)
// here I need to check, If multiple customers are after
// comparing the cost, I have to update the lastPurchasedDate l
// attribute value & then sort it
.thenComparing(Customer::getLastPurchasedDate)
);
// #formatter:on
}
}
If there are multiple customers available after sorting by cost then I need to populate the lastPurchasedDate attribute value and then sort it by lastPurchasedDate.
Why I'm not populating the lastPurchasedDate data before ?
To get that information, I need run a query on db (To get the information, we are going to use a Table which will have millions of records). So it is a performance constraint & I want to avoid it. A very rare scenario of comparing by lastPurchasedDate needed. So I don't want to unnecessarily run this query for all the customers.
This is the solution I came up with...
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
public class Main {
public static void main(String[] args) {
List<Customer> customers = Arrays.asList(new Customer(1, "A", 10, BigDecimal.valueOf(673.89)),new Customer(2, "B", 10, BigDecimal.valueOf(673.89)));
getCustomer(customers).ifPresent(c -> System.out.println(c.getId()));
}
private static Optional<Customer> getCustomer(List<Customer> customers) {
// #formatter:off
return customers.stream()
.max(
Comparator.comparing(Customer::getQuantity)
.thenComparing(Customer::getCost)
.thenComparing(Main::updateLastPurchasedDate)
);
// #formatter:on
}
private static Date updateLastPurchasedDate(Customer c) {
Date lastPurchasedDate = customerRepository.getLastPurchasedDateById(c.getId());
if(lastPurchasedDate == null) {
return new Date(10000);
}
return lastPurchasedDate;
}
}
Assume the data collection object looks like below
i need am trying to use java lambda function to get the matching brand object when the engine matches.
Vehicles Class
- list of Brand
- List of cars
- List of engine
Vehicles
- Honda
- Civic
- Engine1
- Engine2
- Accord
- Engine11
- Engine12
- Toyota
- corolla
- Engine21
now i need to get the brand name if the Engine type matched.
for example if i search Engine1 then the Honda object needs to be returned.
below is the code sample:
Class Vehicle:
import java.util.List;
public class Vehicle {
private List<Brands> brands;
public List<Brands> getBrands() {
return brands;
}
public void setBrands(List<Brands> brands) {
this.brands = brands;
}
}
Class Brand:
import java.util.List;
public class Brands {
private String brandname;
private List<Cars> cars;
public String getBrandname() {
return brandname;
}
public void setBrandname(String brandname) {
this.brandname = brandname;
}
public List<Cars> getCars() {
return cars;
}
public void setCars(List<Cars> cars) {
this.cars = cars;
}
}
Class Cars:
import java.util.List;
public class Cars {
private List<Engines> engines;
public List<Engines> getEngines() {
return engines;
}
public void setEngines(List<Engines> engines) {
this.engines = engines;
}
}
Class Engine:
import java.util.List;
public class Engines {
private List<String> names;
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
}
Class Main:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StreamDemoMain {
public static void main(String args[]){
Vehicle vh = new Vehicle();
List<Brands> brandslist = new ArrayList<>();
Brands brand = new Brands();
Cars car = new Cars();
Engines engine = new Engines();
List<Engines> engineList = new ArrayList<>();
List<String> engineNames = new ArrayList<>();
List<Cars> carList = new ArrayList<>();
brand.setBrandname("toyota");
engineNames.add(brand.getBrandname()+"1");
engineNames.add(brand.getBrandname()+"2");
engine.setNames(engineNames);
engineList.add(engine);
car.setEngines(engineList);
carList.add(car);
brand.setCars(carList);
brandslist.add(brand);
brand = new Brands();
car = new Cars();
engine = new Engines();
engineList = new ArrayList<>();
engineNames = new ArrayList<>();
carList = new ArrayList<>();
brand.setBrandname("honda");
engineNames.add(brand.getBrandname()+"1");
engineNames.add(brand.getBrandname()+"2");
engine.setNames(engineNames);
engineList.add(engine);
car.setEngines(engineList);
carList.add(car);
brand.setCars(carList);
brandslist.add(brand);
vh.setBrands(brandslist);
Map<String,Brands> result = new HashMap<>();
vh.getBrands().stream()
.forEach(eachcars->{eachcars.getCars().stream()
.map(Cars::getEngines)
.flatMap(List::stream)
.peek(a->{System.out.println("before:: "+a.getNames().toString());})
.map(Engines::getNames)
.flatMap(List::stream)
.forEach(engineName -> {
result.put(engineName, eachcars);
});
}
);
//print results and validate the output object
List<Brands> listofBrands = new ArrayList<>();
result.entrySet().stream().forEach(values->{
System.out.println(values.getKey() + " = "+ values.getValue().getBrandname());
if(!listofBrands.contains(values.getValue())){
listofBrands.add(values.getValue());
}
});
System.out.println(listofBrands.size());
}
}
Above is the code i tried.
earlier my objective was to filter with the key in the grant child object list.
now i used that as a key to form a map with the parent or brand object as value.
it is working for my data set. no null checks are done.
welcome suggestion on improvement.
You've left out a lot of details, so I'll assume you have a List<Brand> brands, and that Brand has a method List<Car> getCars(), and Car has a method List<Engine> getEngines(), and you've implemented Engine.equals().
This method will return any brand with a matching engine, if one exists:
Optional<Brand> findBrandByEngine(Engine engine) {
return brands.stream()
.filter(b -> b.getCars()
.stream()
.map(Car::getEngines)
.flatMap(List::stream)
.anyMatch(engine::equals))
.findAny();
}
I need to serialize this:
List<Event>
where the Event class is:
public class Event {
public int id;
public String foo;
public String bar;
}
into JSON of this form:
{
"123":{"foo":"...","bar":"..."},
"345":{"foo":"...","bar":"..."}
}
Taking the "id" property out of Event and storing a Map would do the trick, but I need to support duplicate IDs.
Is there an annotation I can put on the "id" property to cause Jackson to treat it as a key, with the rest of the object as the associated value?
With your current structure of ID as the key, I'm not sure having duplicate IDs is possible in the JSON spec. Maybe if you had arrays with the IDs. I think you need to re-evaluate your desired JSON output.
You could use IdentityHashMap, so you could use different instances of string containing same value and have this result:
{"1":{"foo":"foo1","bar":"bar"},"2":{"foo":"foo2.1","bar":"bar"},"3":{"foo":"foo2","bar":"baz"},"2":{"foo":"foo2","bar":"baz"}}
that you can have executing this:
import java.io.IOException;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.List;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
public class JacksonTest {
public static void main(final String[] args) throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper om = new ObjectMapper();
IdentityHashMap<String, Event> ihm = new IdentityHashMap<String, Event>();
List<Event> list = Arrays.asList( //
new Event(1, "foo1", "bar"), //
new Event(2, "foo2", "baz"), //
new Event(2, "foo2.1", "bar"), //
new Event(3, "foo2", "baz") //
);
for (Event e : list) {
ihm.put(String.valueOf(e.id), e);
}
System.out.println(om.writeValueAsString(ihm));
}
#JsonIgnoreProperties({ "id" })
public static class Event {
public int id;
public String foo;
public String bar;
public Event(final int id, final String foo, final String bar) {
super();
this.id = id;
this.foo = foo;
this.bar = bar;
}
}
}