0

I am teaching my self to code in Java. I am a beginner but not totally clueless about programing. I have decided to make an application that tracks tickets, clients and devices for a computer repair shop. I have made a "lot" of code for that application, but as I said I am a beginner can I don know what is the "right way"(best, smartest and convenient) to implement the data-structure of the application.

I decided to use custom data classes that are value objects in HashMap with integer keys, and that represent data tables that mirror data tables in databases. Am I doing it wrong?

public class Clients
{
    private String firstName;
    private String lastName;
    private String primePhoneNum;
    private String secondPhoneNum;
    private String email;
    private String address;
    private MarketingTypes marketing;

   //getters and setters
}

public HashMap<Integer,Clients> clientsTable = new HashMap<Integer, Clients>();

I ran in to trouble when I tried to make search function that returns value object in a HashMap based on that object particular field value. For example:

public class SearchDeviceTypes
{   
    private Map<Integer, DeviceTypes> deviceTypesTable;

    public SearchDeviceTypes(Map<Integer, DeviceTypes> deviceTypesTable)
    {
        this.deviceTypesTable = deviceTypesTable;
    }

    public boolean isNameTaken(String name)
    {
        return deviceTypesTable.entrySet().stream()
                .anyMatch(deviceType->deviceType.getValue().getName().equals(name));
    }

    public DeviceTypes getByID(int id)
    {
        return deviceTypesTable.get(id);
    }

    public Map<Integer, DeviceTypes> filterByName(String text)
    {
        return  deviceTypesTable.entrySet().stream()
                .filter(deviceType->deviceType.getValue().getName().contains(text))
                .collect(Collectors.toMap(deviceType -> deviceType.getKey(), deviceType -> deviceType.getValue())); 
    }

    public DeviceTypes getByName(String name)
    {
        //How to implement this?
        return null;
    }
}

I would like to help me to learn how to implement this kind of data structure. Thank you in advance!

3
  • Is there a reason you aren't using an actual database and an ORM like hibernate? Commented Sep 30, 2019 at 21:04
  • 1
    same as your filterByName just use .findFirst() instead of the collect may need to map to getValue. Commented Sep 30, 2019 at 21:04
  • Actual database will be implemented later but I wanted to make it so the whole database is in RAM locally, in every client application. This Object-relational mapping that you mentioned, is some thing that I heard for the first time now, I presume is the right thing to make this sort of database in the application? Commented Sep 30, 2019 at 21:19

2 Answers 2

1

You should soften your logic:

public Map<Integer, DeviceTypes> filterByName(String text)
    {
        return  deviceTypesTable.entrySet().stream()
                .filter(deviceType->deviceType.getValue().getName().contains(text))
                .collect(Collectors.toMap(deviceType -> deviceType.getKey(), deviceType -> deviceType.getValue())); 
    }

You simply needs to pass a Predicate<DeviceType> instead of hard coding the logic using .getName().contains(text):

public Map<Integer, DeviceType> filterBy(Predicate<DeviceType> predicate) { 
  Objects.requireNonNull(predicate, "predicate");
  return deviceTypesTable.entrySet().stream()
           .filter(entry ->  predicate.test(entry.getValue())
           .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 
}

You may alias it however:

public Map<Integer, DeviceType> filterByName(String name) {
  Objects.requireNonNull(name, "name");
  return filterBy(dt -> dt.getName().contains(name));
}

Since you want a DeviceType, this give:

public Optional<DeviceType> findFirst(Predicate<DeviceType> predicate) { 
  Objects.requireNonNull(predicate, "predicate");
  return deviceTypesTable.values().stream()
           .filter(predicate)
           .findFirst();
}

The method will return the first DeviceType matching the predicate, for example:

allDevices.findFirst(dt -> "disk".equalsIgnoreCase(dt.name)).ifPresent(dt -> {
  System.out.println("deviceType: " + dt);
});
Sign up to request clarification or add additional context in comments.

5 Comments

This is a very nice answer and I tank you very much for it. Do you think I should do this data structure like I did or I should go about doing it differently? How would you do it?
As said in other comments, to do these you usually use a database or ORM such as Hibernate. If database is your target, Java Predicate won't help you because you'll have to write either Criteria (Hibernate/JPA) which can't use said Predicate (it is Java specific, while a Criteria purpose is to write a JPQL/SQL query in the end) either a SQL query (if using native SQL).
To further explain: my answer works well in your specific case because you have data in memory and it seem rather small (you don't have millions of DeviceType, don't you ?). If you need data in database, then use the right tool: SQL, JPQL, Criteria but don't ever think of loading all entities to use a Java Stream/Predicate.
Well I intend to make it that whole data to be in the RAM. I estimated that in real life use whole database would not be more than 1GB (far less), and that is in the extreme case, and that is acceptable to be in RAM. The database is very normalised. I have Ticket, Devices, Models, Devices Types, Manufacturers, Clients, Parts, Notifications, and some other things. For small repair shop that gets up to 50 service orders per day, even in 10 years you wouldn't get more than one million notifications that are the bulk of the database, these are String with couple of words. It is a small database.
Have i chosen the right way to implement data-structure? With those HashMaps and that kind of custom data object classes? Thank you very much for spending your private time on my problems. I am very grateful!
0

If I understood you well, you need just to put an ID parameter in your class Clients. You don't need to make a structure just for an identifier.

4 Comments

Do you can search for JPA and try to understand the concept to take as basis. public class Clients { private Long id; //add the parameter } and create persistent class with methods for return the object(s) of your needs, in your case in memory. public class ClientsDAO{ ... populated list public List<Clients> findByName(String name){ return this.list.stream().filter( c -> { return c.getFirstName().equals(name); } ).collect(Collectors.toList()); } remember this is a very exbuxulo example
Thank you very much, I will research the JPA. But don't you find that is better to use ID as a key in HashMap than a list, because I intend to store some information in the ID itself and I would get faster search time when accessing data with keys?
as I said before, i not understand well what's your objective but when working with database the ID exist in a tuple and search in database will be much more fast
My objective is to always have the whole database in RAM of the local client application. And just to update changes to and from the database on a sever. I think i figured it out how to correctly implement local data-structure to mirror the database. I have reintroduced int ID in all my data classes, as you suggested, but when the data is used in the program some HashMaps of my data classes will have String keys that are unique fields in those objects for easy filtering code with ComboBoxes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.