I am trying a test with hashmap for a custom class with overridden equals and hashcode method:
public class Car {
public int hashcode() {
return 1;
}
#Override
public boolean equals(Object o1) {
return true;
}
}
Main Class:
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap<Car,String> map = new HashMap<Car,String>();
Car c1 = new Car();
Car c2 = new Car();
System.out.println(c2.equals(c1));
System.out.println(c1==c2);
map.put(c1, "car1");
map.put(c2, "car2");
System.out.println(map.size());
System.out.println(map.get(c1));
}
I expected the output as 1 and car2 but it's 2 and car1. Can anyone explain reason. My Equals is true for each car object and hashcode is also same.
Thanks,
It was a typo.hashcode is not overridden.I created a method hashcode() instead of hashCode(). Correcting that provided the expected result.
Related
I am trying to create an ObservableList() to use with my Tableview. The StringData type is a class containing two SimpleStringProperty var. I want to create this list and bind each variable to an specific position of a List. Something like this:
public class DownloadService implements Runnable {
//List that will be updated
public List<SimpleStringProperty> dList = new ArrayList<SimpleStringProperty>();
public class MainScreenController implements Initializable {
//List that populates TV
private ObservableList<DataString> data = FXCollections.observableArrayList();
//tableview
#FXML
private TableView<DataString> tbl_table;
DownloadService download;
...}
public class DataString{
public final SimpleStringProperty state;
public final SimpleStringProperty sinc;
public SimpleStringProperty stateProperty() {
return state;
}
public void setState(String status) {
state.set(status);
}
public SimpleStringProperty sincProperty() {
return sinc;
}
public void setSinc(String sinc) {
this.sinc.set(sinc);
}
}
On MainScreenController I try to do this:
DataString s = new DataString();
s.state.bind (download.dList.get(data.size()));
s.sinc.bind (download.dList.get(data.size()));
data.add(s);
tbl_table.setItems(data);
However, I cannot update the content of data when I update the list on DownloadService. I believe it should update the value of the column associated with the state and sinc variable everytime DownloadService updated the content of the list in each position. I am doing something wrong or is there another way to bind a StringProperty to a position on the list?
Thanks!
You are binding to the specific object inside the list, not to the position. If using SimpleStringProperty in dList isn't strict requirement, than you can use Bindings.stringValueAt():
StringBinding binding = Bindings.stringValueAt(dList, index);
s.state.bind(binding);
If you really need SimpleStringProperty, you can implement custom StringBinding, something like this:
class CustomStringBinding extends StringBinding {
private ObservableList<SimpleStringProperty> op;
private int index;
public CustomStringBinding(ObservableList<SimpleStringProperty> list, int index) {
this.op = list;
this.index = index;
super.bind(op, op.get(index));
}
#Override
public void dispose() {
super.unbind(op, op.get(index));
}
#Override
protected String computeValue() {
try {
return op.get(index).get();
} catch (IndexOutOfBoundsException ex) {
// log
}
return null;
}
#Override
public ObservableList<?> getDependencies() {
return FXCollections.singletonObservableList(op);
}
}
While executing this test case, following error I'm facing...
Please anyone suggests me in overcoming this issue.
AbortedJobImportTest
testAbortedJobAddedSuccessfullyToExcludedRun
Unknown entity: java.util.LinkedHashMap
org.hibernate.MappingException: Unknown entity: java.util.LinkedHashMap
at com.rsa.test.crawler.CrawlerTestBase.setUp(CrawlerTestBase.groovy:42)
at com.rsa.test.crawler.AbortedJobImportTest.setUp(AbortedJobImportTest.groovy:19)
/*
***
CrawlerTestBase
public class CrawlerTestBase extends GroovyTestCase {
static transactional = false;
def productsModel;
protected JenkinsJobCrawlerDTO jenkinsCrawlerDTO;
def jenkinsJobService;
def httpClientService;
def sessionFactory;
def productModelsService;
protected String JENKINS_URL = "http://10.101.43.253:8080/jenkins/";
protected String JENKINS_JOB_CONSTANT= "job";
protected String JUNIT_TEST_PARAMETERS = "type=junit";
protected String CUSTOM_JUNIT_SELENIUM_TEST_PARAMETERS = "type=selenium,outputfile=Custom-junit-report*";
protected String DEFAULT_PRODUCT = "AM";
public void setUp(){
deleteDataFromTables();
Date date = new Date();
productsModel = new ProductModel(product:DEFAULT_PRODUCT,jenkinsServers:"10.101.43.253",date:date);
if (productsModel.validate()) {
productsModel.save(flush:true);
log.info("Added entry for prodct model for "+DEFAULT_PRODUCT);
}
else {
productsModel.errors.allErrors.each { log.error it }
}
jenkinsCrawlerDTO = new JenkinsJobCrawlerDTO();
productModelsService.reinitialise();
sessionFactory.currentSession.save(flush:true);
sessionFactory.currentSession.clear();
}
public void tearDown(){
deleteDataFromTables();
}
protected void deleteDataFromTables(){
Set<String> tablesToDeleteData = new HashSet<String>();
tablesToDeleteData.add("ExcludedJenkinsRuns");
tablesToDeleteData.add("TestRuns");
tablesToDeleteData.add("ProductModel");
tablesToDeleteData.add("SystemEvents");
tablesToDeleteData.add("JenkinsJobsToCrawl");
tablesToDeleteData.add("TestSuitesInViewList");
tablesToDeleteData.add("JenkinsJobsToCrawl");
(ApplicationHolder.application.getArtefacts("Domain") as List).each {
if(tablesToDeleteData.contains(it.getName())){
log.info("Deleting data from ${it.getName()}");
it.newInstance().list()*.delete()
}
}
sessionFactory.currentSession.flush();
sessionFactory.currentSession.clear();
}
public void oneTimeSetUp(){
}
public void oneTimeTearDown(){
}
}
AbortedJobImportTest
public class AbortedJobImportTest extends CrawlerTestBase {
private String jobUrl = JENKINS_URL+JENKINS_JOB_CONSTANT+"/am-java-source-build/69/";
#Before
public void setUp() {
super.setUp();
jenkinsCrawlerDTO.setJobUrl(jobUrl);
}
#After
public void cleanup() {
super.tearDown();
}
#Test
public void testAbortedJobAddedSuccessfullyToExcludedRun() {
int countBeforeImport = ExcludedJenkinsRuns.count();
jenkinsJobService.handleTestResults(jobUrl,JUNIT_TEST_PARAMETERS);
int countAfterImport = ExcludedJenkinsRuns.count();
Assert.assertEquals(countBeforeImport+1, countAfterImport);
ExcludedJenkinsRuns excludedRun = ExcludedJenkinsRuns.findByJobNameLike(jenkinsCrawlerDTO.jobName);
Assert.assertNotNull(excludedRun);
Assert.assertEquals(jobUrl, excludedRun.jobUrl);
Assert.assertEquals(jenkinsCrawlerDTO.jobName, excludedRun.jobName);
Assert.assertEquals(jenkinsCrawlerDTO.jenkinsServer, excludedRun.jenkinsServer);
Assert.assertEquals(jenkinsCrawlerDTO.buildNumber.toInteger(), excludedRun.buildNumber);
Assert.assertEquals("Build Aborted", excludedRun.exclusionReason);
}
}
*/
I cant figure out the issue in this code. Can anyone help me?
While executing this test case, following error I'm facing...
Please anyone suggests me in overcoming this issue.
It means that you try to put a LinkedHashMap in constructor of Product Model but there is no constructor with LinkedHashMap parameter.
I guess the problem is your Unit Test. The Model constructor will be added by grails framework. You aren`t running grails framework in your Unit Test, because you use GroovyTestCase instead of Spock.
Lock here https://grails.github.io/grails-doc/3.0.5/guide/single.html#unitTesting
i have a problem with conversion of entitys with a version. I made a simple example to explain my problem because the "real" application is to big and contains many unnecessary things.
Situation: I have a web application with primefaces and openjpa. I have 20 components (autocompletes + selectedmenues) that needs a converter and they use persistence entitys.
Informations: I only want use jsf,primefaces for it! (Nothing special like omnifaces or something else.) The Question is at bottom. This is only test-code. It is NOT complete and there are some strange things. But this explain my problem at best.
Example entity: (Only fields and hashcode + equals)
#Entity
public class Person {
#Id
private Long id;
private String name;
#Version
private Long version;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
First solution: My first solution was that i make a own converter for every component.I inject my managed bean there and use the getter from the "value" of the component.
Bean
#ManagedBean(name = "personBean")
#ViewScoped
public class PersonBean implements Serializable {
private List<Person> persons;
/** unnecessary things **/
xhtml:
<p:selectOneMenu >
<f:selectItems value="#{personBean.persons}"/>
</p:selectOneMenu>
converter:
#ManagedBean
#RequestScoped
public class PersonConverter implements Converter{
#ManagedProperty(value = "personBean")
private PersonBean personBean;
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
//null & empty checks
Long id = Long.valueOf(value);
for(Person person : personBean.getPersons()){
if(person.getId().equals(id)){
return person;
}
}
throw new ConverterException("some text");
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
//null & Instanceof checks
return String.valueOf(((Person)value).getId());
}
}
Summary: This solution works good. But i found that there must be a better solution as an converter for every component.
Second solution: I found here on stackoverflow the Global Entity Converter. One converter for all, i thought that was a good solution. ("p:autocomplete for a global Entity Converter"). I use it and i thought it works fine. BUT after a few tests i found another big problem, the version of the entity.
Problem1 with entity converter:
I have the version field not in my hashcode or equals (i found nothing about it). I only read this (The JPA hashCode() / equals() dilemma) about it. The problem is that the entity will not replaced in the hashmap and in some cases i get an optimistic locking exception because the "old" entity stays in the hashmap.
if (!entities.containsKey(entity)) {
String uuid = UUID.randomUUID().toString();
entities.put(entity, uuid);
return uuid;
} else {
return entities.get(entity);
}
Solution: I thought that i can resolve this problem by adding an interface to my entitys that checks whether a version exists.
Interface:
public interface EntityVersionCheck {
public boolean hasVersion();
}
Implementation:
#Override
public boolean hasVersion() {
return true;
}
Converter:
#Override
public String getAsString(FacesContext context, UIComponent component, Object entity) {
synchronized (entities) {
if(entity instanceof EntityVersionCheck && ((EntityVersionCheck)entity).hasVersion()){
entities.remove(entity);
}
if (!entities.containsKey(entity)) {
String uuid = UUID.randomUUID().toString();
entities.put(entity, uuid);
return uuid;
} else {
return entities.get(entity);
}
}
}
This solution works for the optimistic locking exception but brings another problem!
Problem2 with entity converter:
<p:selectOneMenu value="#{organisation.leader}">
<f:selectItems value="#{personBean.persons}"/>
</p:selectOneMenu>
If a organisation has already a leader. It will be replaced with a new uuid if the leader is in the persons - list, too. The leader will be set to null or convert exception because the uuid does not exists anymore in the hashmap. It means he use the converter for the organisation.leader and add the leader to the hashmap. Than comes the persons- List and add all other persons in a hashmap and override the uuid from the organisation.leader if he exists in persons, too.
Here are two cases now:
When i select a other leader, it works normally.
If i dont change the "current" selection and submit the organisation.leader tries to find his "old" uuid but the other person from the person list has override it and the uuid does not exists and the organisation.leader is null.
I found another solution for it and this is my final solution BUT i find, that is a very very strange solution and i will do this better but i found nothing about it.
Final Solution
I add the "old" uuid to the "new" object.
#Override
public String getAsString(FacesContext context, UIComponent component,
Object entity) {
synchronized (entities) {
String currentuuid = null;
if (entity instanceof EntityVersionCheck
&& ((EntityVersionCheck) entity).hasVersion()) {
currentuuid = entities.get(entity);
entities.remove(entity);
}
if (!entities.containsKey(entity)) {
if (currentuuid == null) {
currentuuid = UUID.randomUUID().toString();
}
entities.put(entity, currentuuid);
return currentuuid;
} else {
return entities.get(entity);
}
}
}
Question: How i make this better and right?
If Solution 1 worked and you just want it more generic:
Holding your instances within scope of a bean you can use a more generic converter by removing the managed-bean lookup from it. Your entities should inherit from a base entity with a identifier property. You can instantiate this converter in your bean where you retrieved the entities.
Or use a guid map or public identifier if id should not be exposed in html source.
#ManagedBean(name = "personBean")
#ViewScoped
public class PersonBean implements Serializable {
private List<Person> persons;
private EntityConverter<Person> converter;
// this.converter = new EntityConverter<>(persons);
}
<p:selectOneMenu converter="#{personBean.converter}">
<f:selectItems value="#{personBean.persons}"/>
</p:selectOneMenu>
Abstract Base Entity converter:
/**
* Abstract Entity Object JSF Converter which by default converts by {#link Entity#getId()}
*/
public abstract class AEntityConverter<T extends Entity> implements Converter
{
#Override
public String getAsString(final FacesContext context, final UIComponent component, final Object value)
{
if (value instanceof Entity)
{
final Entity entity = (Entity) value;
if (entity.getId() != null)
return String.valueOf(entity.getId());
}
return null;
}
}
Cached collection:
/**
* Entity JSF Converter which holds a Collection of Entities
*/
public class EntityConverter<T extends Entity> extends AEntityConverter<T>
{
/**
* Collection of Entity Objects
*/
protected Collection<T> entities;
/**
* Creates a new Entity Converter with the given Entity Object's
*
* #param entities Collection of Entity's
*/
public EntityConverter(final Collection<T> entities)
{
this.entities = entities;
}
#Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
{
if (value == null || value.trim().equals(""))
return null;
try
{
final int id = Integer.parseInt(value);
for (final Entity entity : this.entities)
if (entity.getId().intValue() == id)
return entity;
}
catch (final RuntimeException e)
{
// do something --> redirect to exception site
}
return null;
}
#Override
public void setEntities(final Collection<T> entities)
{
this.entities = entities;
}
#Override
public Collection<T> getEntities()
{
return this.entities;
}
}
Remote or database lookup Converter:
/**
* Entity Object JSF Converter
*/
public class EntityRemoteConverter<T extends Entity> extends AEntityConverter<T>
{
/**
* Dao
*/
protected final Dao<T> dao;
public EntityRemoteConverter(final EntityDao<T> dao)
{
this.dao = dao;
}
#Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
{
// check for changed value
// no need to hit database or remote server if value did not changed!
if (value == null || value.trim().equals(""))
return null;
try
{
final int id = Integer.parseInt(value);
return this.dao.getEntity(id);
}
catch (final RuntimeException e)
{
// do someting
}
return null;
}
}
I use dao approach whenever I have to convert view-parameters and bean was not constructed yet.
Avoid expensive lookups
In dao approach you should check if the value has changed before doing potential expensive lookups, since converters could be called multiple times within different phases.
Have a look at source of: http://showcase.omnifaces.org/converters/ValueChangeConverter
This basic approach is very flexible and can be extended easily for many use cases.
I want to store many details (like name, email, country) of the particular person using the same key in hashtable or hashmap in java?
hashMap.put(1, "Programmer");
hashMap.put(2, "IDM");
hashMap.put(3,"Admin");
hashMap.put(4,"HR");
In the above example, the 1st argument is a key and 2nd argument is a value, how can i add more values to the same key?
You can achieve what you're talking about using a map in each location of your map, but it's a little messy.
Map<String, Map> people = new HashMap<String, Map>();
HashMap<String, String> person1 = new HashMap<String, String>();
person1.put("name", "Jones");
person1.put("email", "jones#jones.com");
//etc.
people.put("key", person1);
//...
people.get("key").get("name");
It sounds like what you might really want, though, is to define a Person class that has multiple properties:
class Person
{
private String name;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//plus getters and setters for other properties
}
Map<String, Person> people = new HashMap<String, Person>();
person1 = new Person();
person1.setName("Jones");
people.put("key", person1);
//...
people.get("key").getName();
That's the best I can do without any information about why you're trying to store values in this way. Add more detail to your question if this is barking up the wrong tree.
I think what you are asking
let us assume you we want to store String page, int service in the key and an integer in the value.
Create a class PageService with the required variables and define your HashMap as
Hashmap hmap = .....
Inside pageService, what you need to do is override the equals() and hashcode() methods. Since when hashmap is comparing it checks for hashcode and equals.
Generating hashcode and equals is very easy in IDEs. For example in eclipse go to Source -> generate hashcode() and equals()
public class PageService {
private String page;
private int service;
public PageService(String page, int service) {
super();
this.page = page;
this.service = service;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public int getService() {
return service;
}
public void setService(int service) {
this.service = service;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((page == null) ? 0 : page.hashCode());
result = prime * result + service;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PageService other = (PageService) obj;
if (page == null) {
if (other.getPage() != null)
return false;
} else if (!page.equals(other.getPage()))
return false;
if (service != other.getService())
return false;
return true;
}
}
The following class is very generic. You can nest ad infinitum. Obviously you can add additional fields and change the types for the HashMap. Also note that the tabbing in the toString method should be smarter. The print out is flat.
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HierarchicalMap
{
private String key;
private String descriptor;
private Map<String,HierarchicalMap>values=new HashMap<String,HierarchicalMap>();
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public void addToSubMap(String key, HierarchicalMap subMap)
{
values.put(key, subMap);
}
public String getDescriptor()
{
return descriptor;
}
public void setDescriptor(String descriptor)
{
this.descriptor = descriptor;
}
public HierarchicalMap getFromSubMap(String key)
{
return values.get(key);
}
public Map<String,HierarchicalMap> getUnmodifiableSubMap()
{
return Collections.unmodifiableMap(values);
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("HierarchicalMap: ");
sb.append(key);
sb.append(" | ");
sb.append(descriptor);
Iterator<String> itr=values.keySet().iterator();
while(itr.hasNext())
{
String key= itr.next();
HierarchicalMap subMap=this.getFromSubMap(key);
sb.append("\n\t");
sb.append(subMap.toString());
}
return sb.toString();
}
I am trying to figure out a way to have a class full of static objects which each can have a variety of static properties.
I want to be able to pass these properties around and even set them as static properties of other object and I also want to be able to switch through the objects.
Here is an example illustrating what I mean:
Creating and Sending a Message
class Program
{
static void Main(string[] args)
{
MarketOrder Order = new MarketOrder("DELL", MessageProperties.SecurityType.Equity, MessageProperties.ExchangeDestination.ARCA.PostOnly);
SendOrder(Order);
Console.ReadLine();
}
public static void SendOrder(MarketOrder Order)
{
switch (Order.SecurityType)
{
case MessageProperties.SecurityType.Equity:
// Equity sending logic here
break;
case MessageProperties.SecurityType.Option:
// Option sending logic here
break;
case MessageProperties.SecurityType.Future:
// Future sending logic here
break;
}
}
}
This does not want to compile because it won't let me switch the Order.SecurityType object.
MarketOrder Class
public class MarketOrder
{
public readonly string Symbol;
public readonly MessageProperties.SecurityType SecurityType;
public readonly MessageProperties.ExchangeDestination ExchangeDestination;
public MarketOrder(string Symbol, MessageProperties.SecurityType SecurityType, MessageProperties.ExchangeDestination ExchangeDestination)
{
this.Symbol = Symbol;
this.SecurityType = SecurityType;
this.ExchangeDestination = ExchangeDestination;
}
}
MessageProperties Class
public abstract class MessageProperties
{
public class ExchangeDestination
{
public readonly string Value;
public readonly double ExchangeFee;
public ExchangeDestination(string Value, double ExchangeFeed)
{
this.Value = Value;
this.ExchangeFee = ExchangeFee;
}
public abstract class ARCA
{
public static ExchangeDestination Only = new ExchangeDestination("ARCA.ONLY", 0.01);
public static ExchangeDestination PostOnly = new ExchangeDestination("ARCA.ONLYP", 0.02);
}
public abstract class NYSE
{
public static ExchangeDestination Only = new ExchangeDestination("NYSE.ONLY", 0.01);
public static ExchangeDestination PostOnly = new ExchangeDestination("NYSE.ONLYP", 0.03);
}
}
public class SecurityType
{
public readonly string Value;
public SecurityType(string Value)
{
this.Value = Value;
}
public static SecurityType Equity = new SecurityType("EQ");
public static SecurityType Option = new SecurityType("OPT");
public static SecurityType Future = new SecurityType("FUT");
}
}
Enums work perfectly for what I am trying to do except it is hard to have multiple properties of an enum value. I considered using Attributes on Enums to set the properties but getting those vs. getting static properties of objects is substantially slower and my application is extremely speed/latency sensitive.
Is there perhaps a better way of accomplishing what I am trying to do?
Thanks in advance for your help!
William