How to check that List<Long> contains a value? - java

I have list List<Long> list, that contains: [160774, 7212775] and Long id = 7212775. I need to check if the list contains an element with value of id. How to do that? Unfortunately list.contains(id) returns false in my case.
I'm using it that way:
#RequestMapping("/case/{id}")
public String openCase(#PathVariable("id") Long id) {
log.debug(caseDAO.findAllCasesId()); // [160774, 7212775]
log.debug(id); // 7212775
if(caseDAO.findAllCasesId().contains(id)) {
return "case";
} else {
return "404";
}
}
Piece of DAO (Hibernate, but native sql here):
public List<Long> findAllCasesId() {
String sql = "select id from cases";
SQLQuery query = getSession().createSQLQuery(sql);
return query.list();
}
SOLVED
The problem was with caseDAO.findAllCasesId(), that return list of Object, not list of Long. I corrected this by:
SQLQuery query = getSession().createSQLQuery(sql).addScalar("id", Hibernate.LONG);
Big thanks to: Nayuki Minase

When autoboxing, you need to make sure you postfix the literal with an L i.e. Long id = 7212775L for this to work.

Running the code below on eclipse helios:
public static void main(String[] args) {
List<Long> list = new ArrayList<Long>();
list.add(160774L);
list.add(7212775L);
System.out.println(list.contains(7212775L);
}
Output:
true
What you're doing wrong is
System.out.println(list.contains(7212775));
The problem is that your list takes Long objects and you are searching for a literal.

List<Long> list = new ArrayList<Long>(Arrays.asList(160774L, 7212775L));
Long id = 7212775L;
System.out.println(list.contains(id)); // prints true

Hum, I believe List list should return true in your case.
The following piece of code returns true.
List<Long> listOfLongs = new java.util.ArrayList<Long>();
listOfLongs.add(160774L);
listOfLongs.add(7212775L);
return listOfLongs.contains(7212775L);
Same with
List<Long> listOfLongs = new java.util.ArrayList<Long>();
listOfLongs.add(Long.valueOf(160774L));
listOfLongs.add(Long.valueOf(7212775L));
return listOfLongs.contains(Long.valueOf(7212775L));
If you could show us the code where this ain't working, it would help.

Related

How to delete a list of entities

I have a JPA query to delete selected entities which is stored in a list. I am currently deleting the entities in a loop via the in built JPA delete() method 1 by 1. Is there a way to just pass in the list instead of looping it?
Current implementation that works but looping to delete 1 by 1. I need the initial query to get list of entities for other reasons thus not looking to change that. Just a way to pass in the list of entiies to be deleted. Please advice. Thanks.
Note: This is with Java 8 and Spring 4.3 if it matters.
#GetMapping("/delete/{name}/{count}")
public String delete(#PathVariable String name, #PathVariable int count){
boolean isDelete = true;
while (isDelete){
//1st query
List<PersonEntity> results = personService.get(name, count);
if(results != null && !results.isEmpty()){
System.out.println("Deleting following: ");
//2nd query
results.forEach(p -> {
System.out.println(p.getName());
personService.delete(p);
});
} else {
isDelete = false;
}
}
return "Done!";
}
You can try something like this:
List<PersonEntity> results = personService.get(name, count);
if(results != null && !results.isEmpty()) {
List<Integer> personIds = results.stream()
.map(personIds)
.collect(Collectors.toList());
personService.deleteManyById(personIds);
In your service:
public void deleteManyById(List<Integer> ids) {
personRepository.deleteByIdIn(ids);
}
In your repo (assuming it's a spring JpaRepository):
void deleteByIdIn(List<Integer> ids);
Just be aware of the fact that dbs have a limit in the number of parameters you can pass in a IN condition

JAVA - Reading CSV file based on another CSV file

I am struggling with making this work properly. So I have two CSV Files.
And this One
So the main thing is. I have SearchTerms in 2nd CSV. In first CSV I have SearchTerms also, which should work as a "tag".
What I need is to get product ids from first CSV saved to a List < String > based on, what searchterm from 2nd csv is used. So when Akt (pan) is used, one set of List of IDS is exported. If there is more Akt (pan) sets of ids, they are saved to one list as array I guess.
I tried to read it with CSVloaders and searching it with lookup() method
private final Map<List<String>, Comparison> data = Maps.newHashMap();
public Comparison lookup(String searchTerm) {
return data.get(searchTerm);
}
Where Comparison Class is
public class Comparison {
#Parsed(field = "ProductId1")
private String productId1;
#Parsed(field = "ProductId2")
private String productId2;
#Parsed(field = "ProductId3")
private String productId3;
#Parsed(field = "SearchTerm")
private String SearchTerm;
public String getProductId1() {
return productId1;
}
public String getProductId2(){
return productId2;
}
public String getProductId3(){
return productId3;
}
public List<String> getProductIds(){
List<String> ids = new ArrayList<>();
Collections.addAll(ids, productId1, productId2, productId3);
return ids;
}
}
My solution was bad. I was getting NullPointerException constantly whenever I tried to use lookup() method.
Do you have any ideas how to make this work? Thank oyu
Problem is with the data type of key in your HashMap. It should be a string as per your data, not a List<>.
private final Map<String, Comparison> data = Maps.newHashMap();
public Comparison lookup(String searchTerm) {
return data.get(searchTerm);
}
Then the returning object(typed Comparison) would have the all products Ids for the given search Term.

Spring-Data-SOLR: Stats result on SimpleQuery won't return me distinct calcs

I'm trying to use a SimpleQuery to get distinct result from my solr collection, but even after setting my StatsOption with calcDistinct true, I can't get the result I want.
BTW I'm using spring-data-solr-2.1.4.RELEASE.
SampleCode:
Field field = new SimpleField("fieldName");
StatsOptions statsOptions = new StatsOptions().addField(field).setCalcDistinct(true);
SimpleQuery query = new SimpleQuery("*:*").setStatsOptions(statsOptions);
StatsPage<MyClass> statsPage = solrTemplate.queryForStatsPage(query, MyClass.class);
FieldStatsResult statsResult = statsPage.getFieldStatsResult(field);
Collection<Object> distinctValues = statsResult.getDistinctValues();
Set<String> result = distinctValues.stream().map((i) -> i.toString()).collect(Collectors.toSet());
return result;
After trying the above code, all I get is the max, min, count, but no results for distinct totals or distinct values.
What am I doing wrong in this sample?
Looks like your disctintValues collection is also an implementation of EmptyList which means that there are no values in the response.
Check if your query returns any result, first.
StatsOptions statsOptions = new StatsOptions().addField(field).setSelectiveCalcDistinct(true).setCalcDistinct(true);
The processStatsOptions method in org.springframework.data.solr.core.DefaultQueryParser is described as follows :
Boolean selectiveCountDistincts = statsOptions.isSelectiveCalcDistincts(field);
if (selectiveCountDistincts != null) {
solrQuery.add(selectiveCalcDistinctParam, String.valueOf(selectiveCountDistincts.booleanValue()));
}

after string formatting method result changes

I'm using force-rest-api to do queries to salesforce and retrieve json answer and make java object.
public class SomeObject {
#JsonProperty("field")
private String field;
#JsonProperty("list")
private List<AnotherObject> list;
}
When I query string plainly - it returns correct result.
String requestQuery1 = "SELECT ... ='1111'";
return forceApi.query(requestQuery, clazz); // both field and list have data
But when add wildcard and use string format to create parametrized query - it returns incorrect result
String requestQuery = "SELECT ... ='%s'";
requestQuery = String.format(query, (Object[]) queryParams); // array of parameters. usually new Object[] { 1111 }.
return forceApi.query(requestQuery, clazz); // field is not null, list is null
I tried to check strings using
assert requestQuery1.equals(requestQuery);
but they are the same. When I put requestQuery manually using debug and set its value
"SELECT ... ='1111'"
It works fine.
But why it doesn't work when I use formatting? What's the problem?

Getting list of lists in Hibernate

In my project I have two entities: Race and RaceDriver, which has-a Race in it:
class RaceDriver {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "race", nullable = false)
private Race race;
...
#Column(name = "starting_nr")
private Integer startingNr;
...
#Column(name = "disqualified", nullable = false)
private boolean disqualified;
}
Now, what I wanted is to get the list of the startingNrs of the disqualified RaceDrivers in a Race, which looked like this:
public List<Integer> findDisqualifiedDriversStartingNumbers(Integer raceId) {
ProjectionList projection = Projections.projectionList()
.add(Projections.property("startingNr").as("startingNr"));
return getSession()
.createCriteria(RaceDriver.class)
.setProjection(projection)
.add(Restrictions.eq("race.id", raceId))
.add(Restrictions.eq("disqualified", true))
.list();
}
The thing is that now I need the same, but for the few Races. How can I achieve this without making a separate DAO calls? Because I've heard that it is better to make as much as possible in a single database call.
My idea is to simply get the list of the drivers which are disqualified in the given races, and then parse it in the Java code, which I think will require few loops, and make some map of disqualified RaceDriver's starting numbers, where the key would be Race.id.
The DAO attempt looks like that:
public List<RaceDriver> findDisqualifiedDriversInRaces(List<Integer> raceIds) {
return getSession()
.createCriteria(RaceDriver.class)
.add(Restrictions.in("race.id", raceIds))
.add(Restrictions.eq("disqualified", true))
.list();
}
The problem is that I will get that big objects, instead of some map or list of the only data I need (startingNr and race.id).
So the question is - can I do it somehow using only Hibernate?
Personally I would use the solution in plain java because it'll be more clear for any developer supporting your code in the future.
Answering the question "can it be done via Hibernate?": yes, it can be, ResultTransformer is the right way, especially if map-of-lists conversion is required more than once in your program. There is no standard transformer for your needs but you can write your own one:
public class MapOfListsResultTransformer<K, V> extends BasicTransformerAdapter {
public List transformList(List collection) {
final Map<K, List<V>> map = new HashMap<>();
for (Object object : collection) {
final Object[] objects = (Object[]) object;
final K key = (K) objects[0];
final V value = (V) objects[1];
if (!map.containsKey(key)) {
final List<V> list = new ArrayList<V>();
list.add(value);
map.put(key, list);
} else {
map.get(key).add(value);
}
}
return Arrays.asList(map);
}
}
And its usage is the following:
public Map<Integer, List<Integer>> findDisqualifiedDriversInRaces(List<Integer> raceIds) {
ProjectionList projection = Projections.projectionList()
.add(Projections.property("race.id").as("race.id"))
.add(Projections.property("startingNr").as("startingNr"));
return (Map<Integer, List<Integer>>) getSession()
.createCriteria(RaceDriver.class)
.setProjection(projection)
.add(Restrictions.in("race.id", raceIds))
.add(Restrictions.eq("disqualified", true))
.setResultTransformer(new MapOfListsResultTransformer<Integer, Integer>())
.uniqueResult();
}
You'll want to create a Query with hibernate that has two WHERE conditions.
#PersistenceContext protected EntityManager em;
List<Integer> raceIds = Arrays.asList(1, 2, 3);
Query query = em.createQuery("FROM RaceDriver r WHERE r.raceId IN (:raceIds) AND r.disqualified = true");
query.setParameter("raceIds", raceIds);
List<RaceDriver> drivers = query.getResultList();
This will return a list of disqualified drivers within the raceIds that you've provided.
Update
After getting List<RaceDriver> you can for loop on drivers and make List of HashMaps with raceId as a key, and a List of startingNr (of disqualified drivers) as a value.
HashMap<Integer,List<Integer>> startingNrHashMap=new...;
for(RaceDriver driver:drivers)
{
List<Integer> strNr = new ArrayList<Integer>();
if(startingNrHashMap.containsKey(driver.race.raceid))
{
//if race id is already present in hash map then
strNr = startingNrHashMap.get(driver.race.raceid);
strNr.add(driver.startingNr);
startingNrHashMap.put(driver.race.raceid,strNr);
}
else
{
// if race id is NOT present in hash map
strNr.add(driver.startingNr);
startingNrHashMap.put(driver.race.raceid,strNr);
}
strNr =null;
}
This is how I did it:
DAO method:
public List<RaceDriver> findDisqualifiedDriversInRaces(List<Integer> raceIds) {
if (!raceIds.isEmpty()) { // it will crash if the list will have no elements!
return getSession()
.createCriteria(RaceDriver.class)
.add(Restrictions.in("race.id", raceIds))
.add(Restrictions.eq("disqualified", true))
.list();
}
return Collections.emptyList();
}
Then to extract from it what I wanted, I created an auxiliary method:
// key = race.id, value = list of disqualified raceDrivers' starting numbers
private HashMap<Integer, List<Integer>> extractStartingNumbersToMap(List<RaceDriver> disqualifiedDrivers) {
HashMap<Integer, List<Integer>> disqualifiedDriversMap = new HashMap<>();
for (RaceDriver raceDriver : disqualifiedDrivers) {
Integer raceId = raceDriver.getRace().getId();
if (!disqualifiedDriversMap.containsKey(raceId)) {
disqualifiedDriversMap.put(raceId, new ArrayList<>(Arrays.asList(raceDriver.getStartingNr())));
} else {
disqualifiedDriversMap.get(raceId).add(raceDriver.getStartingNr());
}
}
return disqualifiedDriversMap;
}
I did it before Mark T has answered, as you can see it's very similar. However I'm posting it, as it could be helpful to someone.
I asked the same kind of question, Its about NHibernate and .NET MVC but you can get idea of DAO and ResultTransformer
Question

Categories