make common method for different data querying - java

Suppose I have similar methods that does almost same thing How do I make it one method that will query different data. Here only the dataManager querying data is different and gets different Object Lists for iteration.
private void method1(ClassA classA){
List<One> one = dataManager.getOne(classA.param1);
if (one != null){
//iterate data here...
for (int i = 0; i < one.size(); i++)
{
one.get(i).getAttributeOne();
one.get(i).getAttributeTwo();
}
}else{
}
}
private void method2(ClassA classA){
List<Two> two = dataManager.getTwo(classA.param1);
if (two != null){
//iterate data here...
}else{
}
}

Do the call to dataManager.get() in the calling method, and use generics to handle the different list types.
private <T> void method1(ClassA classA, List<T> myList){
if (myList != null){
//iterate data here...
}else{
}
}
// Calling code
method1(myClassA, dataManager.getOne(myClassA.param1));
method1(myClassA, dataManager.getTwo(myClassA.param1));
Here is a compilable example that looks like what you are trying to solve.
import java.util.*;
public class Iterate{
private <T> void method1(int classA, List<T> L){
for (T t: L) {
System.out.println(t);
}
}
public static void main(String[] args) {
List<Integer> iList = new ArrayList<Integer>();
List<String> sList = new ArrayList<String>();
new Iterate().method1(1, iList);
new Iterate().method1(1, sList);
}
}

Related

Sort an Object list with Collections having only list as parameter in Java

I have an assignment says printing a object list with given main class:
public static void main(String[] args) throws IOException {
ArrayList<LoaiPhong> ds = new ArrayList<>();
Scanner in = new Scanner(new File("xx.in"));
int n = Integer.parseInt(in.nextLine());
while(n-->0){
ds.add(new LoaiPhong(in.nextLine()));
}
Collections.sort(ds); //this only include object list
for(LoaiPhong tmp : ds){
System.out.println(tmp);
}
}
static class LoaiPhong {
String line;
public LoaiPhong(String line) {
this.line = line;
}
}
So that's mean i have to do something outside the main class to sort the list. Can anyone suggest what to do to sort the object list by its property?
Edit: Thanks to Gus i have the answer, the new class look something like this
static class LoaiPhong implements Comparable<LoaiPhong> {
...
#Override
public int compareTo(LoaiPhong_.LoaiPhong o) {
return <Some logic here>;
}
}

Creating size method for list implementation

I need to implement my own List.size() method. I create such a method :
public class MyArrayList<Long> implements List<Long> {
List<Long> list;
#Override
public int size() {
if(list == null) {
throw new NullPointerException("List is null");
}
int size = 0;
for(Long element : list) {
size++;
}
return size;
}
I write an abstract test class to do the test for the existing method of size and mine.
public abstract class AbstractArrayListTest {
protected abstract List<Long> getEmptyList();
protected abstract List<Long> getSizeOfTheList();
#Test
public void shouldReturnFalseIfListContainElement() {
assertTrue(getEmptyList().isEmpty());
}
#Test
public void shouldReturnSizeOfList() {
int size = getSizeOfTheList().size();
assertEquals(size, getEmptyList().size());
}
}
Every time I try to test it a get null E. Any thought how I can write it ? Worth to mention the original implementation of List is passing this test.
You're not initializing the list you're wrapping over. When you're trying to iterate over it, you're getting a NPE. Please, try the following class definition:
public class MyArrayList<Long> implements List<Long> {
List<Long> list = new ArrayList<>();
// rest of the code
}

Template method pattern in java

I have assignment in java ,I need help please.
I tried to solve it but I have some problem that can't understand them.
Assignment is:
In this exercise, use the Template method pattern to define an abstract class Filter with a public method filter (the template method) that calls the method accept (the hook method) that can be implemented in different ways in the different concrete classes. Write a test program by extending the class Filter and defining accept so that only strings of at most three characters are accepted.
public abstract class Filter<T> {
public abstract T[] filter(T[] list);
public abstract boolean accept(T val);
}
public class FilterTest<T> extends Filter<T> {
private int capacity = 0;
public FilterTest(int cap) {
this.capacity = cap;
}
#Override
public T[] filter(T[] list1) {
#SuppressWarnings("unchecked")
T[] finalList = (T[]) Array.newInstance(list1.getClass().getComponentType(), capacity);
int counter = 0;
for (T t : list1) {
if (accept(t)) {
finalList[counter] = t;
counter++;
}
}
return finalList;
}
public void printArray(T[] list2) {
for (int i = 0; i < list2.length; i++) {
if (list2[i] != null) {
System.out.print(list2[i] + " ");
}
}
System.out.println();
}
#Override
public boolean accept(T val) {
return String.valueOf(val).length() > 0 &&
String.valueOf(val).length() <= 3;
}
public static void main(String[] args) {
FilterTest<String> filterTest = new FilterTest<>(8);
String[] lists = {
"Hi", "here", "is", "the", "AOOP", "course", "at", "University"
};
System.out.print("My original list is: ");
filterTest.printArray(lists);
System.out.print(" The filtered list is: ");
String[] filteredList = filterTest.filter(lists);
filterTest.printArray(filteredList);
}
}
Here is comment from my teacher:
"not correct, only the accept method should be abstract in the Filter class, the filter method should be already implemented in the Filter class and not be abstract all implementation will be the same, only the accept method changes for different filters)".
I don't understand what should I do now, how the code will be correct.
help please,
Thanks
I assume that Filter should look something like this
public abstract class Filter<T> {
public T[] filter(T[] list1) {
#SuppressWarnings("unchecked")
T[] finalList = (T[]) Array.newInstance(list1.getClass().getComponentType(), capacity);
int counter = 0;
for (T t : list1) {
if (accept(t)) {
finalList[counter] = t;
counter++;
}
}
return finalList;
}
public abstract boolean accept(T val);
}
You can even declare Filter<T> as an interface and have a default implementation for filter. Have a look here

Create instances of dynamically given classes in Java

I need a function to create instances of a dynamically given class in java.
I had found many samples but in all of them, the class to be instantiated was known before runtime.
There are user defined classes:
class Student { //some code }
class Teacher { //some code }
class Course { //some code }
What I need is
List<class> MyFunction(<class>) {
List<class> items = new ArrayList<class>();
for(int i = 0; i < 5; i++) {
create_a_new_class_instance;
items.add(new_created_instance);
}
return items;
}
How will I use
List<Student> students = MyFunction(Student);
List<Teacher> teachers = MyFunction(Teacher);
List<Course> courses = MyFunction(Course);
Hope someone helps.
This is my first question in Stackoverflow, sorry for any inconvenience.
Utku
In Java 8, you can use a method reference or lambda expression in order to create instances of classes dynamically without using reflection.
public static <T> List<T> myFunction(Supplier<T> supplier) {
return Stream.generate(supplier)
.limit(5)
.collect(Collectors.toList());
}
You would call it like:
List<Student> students = myFunction(Student::new);
If you're not familiar with streams, the imperative equivalent is:
public static <T> List<T> myFunction(Supplier<T> supplier) {
int size = 5;
List<T> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(supplier.get());
}
return list;
}
This should work.
import java.util.ArrayList;
import java.util.List;
public class DynamicClassList {
public <T> List<T> myFunction(Class<T> inputClass) {
List<T> items = new ArrayList<T>();
for(int i = 0; i < 5; i++) {
try {
T myT = inputClass.getConstructor().newInstance();
items.add(myT);
} catch (Exception e) {
e.printStackTrace();
}
}
return items;
}
public static void main(String[] args) {
DynamicClassList dynamicClassList = new DynamicClassList();
List<Student> s = dynamicClassList.myFunction(Student.class);
List<Teacher> t = dynamicClassList.myFunction(Teacher.class);
List<Course> c = dynamicClassList.myFunction(Course.class);
}
}
Assuming that the classes supplied to MyFunction have a default constructor, a simple implementation would be
public static <T> List<T> MyFunction(Class<T> clazz) {
if (clazz == null) {
return null;
}
T item;
List<T> items = new ArrayList<T>();
for (int i = 0; i < 5; i++) {
try {
item = clazz.newInstance();
} catch (Exception e) {
item = null;
}
if (item != null) {
items.add(item);
}
}
return items;
}
and the above method could be called like
List<Student> student = MyFunction(Student.class);
For increased transparency, the exception thrown inside the method could be handled in another way (e.g., added to the method signature).
You could use reflection to do this
each class you pass must have a default no-argument constructor.
for this specific application you will likely need all 3 classes to share an interface so that you can properly send a list back
public interface Unit {
//Put any common functionality method stubs here
}
public class Teacher implements Unit {
}
//....etc for the other classes
List<Unit> MyFunction(Class<Unit> clazz) {
List<Unit> items = new ArrayList<Unit>();
for(int i = 0; i < 5; i++) {
items.add(clazz.newInstance());
}
return items;
}
when you assign your list to a list variable you will have to cast it.
such as:
List<Student> students = (List<Student>) MyFunction(Student.class);
you can use a pattern stategy like this :
///interface
package strategy;
public interface IStrategy {
public void appliquerStrategy();
}
package tpdesignpattern2.strategy;
public class StrategyImpl1 implements IStrategy{
#Override
public void appliquerStrategy() {
System.out.println("Appliquer la strategy 1");
}
}
package tpdesignpattern2.strategy;
public class StrategyImpl2 implements IStrategy{
#Override
public void appliquerStrategy() {
System.out.println("Appliquer la strategy 2");
}
}
/////// Context class
package tpdesignpattern2.strategy;
public class Context {
/***
* injection de l'interface
*/
private IStrategy iStrategy = new StrategyImpl1() ;
/**
* #param iStrategy
*/
public void setiStrategy(IStrategy iStrategy) {
this.iStrategy = iStrategy;
}
public void appliquerStrategy() {
iStrategy.appliquerStrategy();
}
}
///Application
package tpdesignpattern2.strategy;
import java.util.Scanner;
import strategy.IStrategy;
public class App {
public static void main(String[] args) {
Context context = new Context();
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.print("Entrer le nom de la calss : ");
String nom = "tpdesignpattern2.strategy."+scanner.nextLine();
tpdesignpattern2.strategy.IStrategy strategy;
try {
strategy = (tpdesignpattern2.strategy.IStrategy) Class.forName(nom).newInstance();
context.setiStrategy(strategy);
context.appliquerStrategy();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
}
}
}

Generic List initialization in java

I have a problem with the initialization of a List . The Class of the Items isn't known at compile time - they could be int, float, string or custom classes.
So I tried this:
public class Sensordevice {
private List<?> valueList;
public void setValueList(List<?> valueList) {
this.valueList = valueList;
}
public void addValue(Object value) {
if(valueList == null){
valueList = getList(value.getClass());
}
valueList.add(value);
}
private <T> List<T> getList(Class<T> requiredType) {
return new ArrayList<T>();
}
}
But I get this Error at valueList.add(value) in the addValue Methode:
The method add(capture#4-of ?) in the type List is not applicable for the arguments (Object)
Update
Thanks a lot for your replies. This solution works for my.
public class Sensordevice<T> {
private List<T> valueList;
public void setValueList(List<T> valueList) {
this.valueList = valueList;
}
public void addValue(T value) {
if(valueList == null){
valueList = new ArrayList<T>();
}
valueList.add(value);
}
}
This works for me. And by "works" I mean I don't get any errors. It doesn't seem to provide any functionality since there isn't any way to get the list of objects from the Sensordevice since getList just returns a new, empty list, but that's the code you gave. I think the core of the error is having addValue take Object instead of T.
public class Sensordevice {
private List valueList;
public <T> void setValueList(List<T> valueList) {
this.valueList = valueList;
}
public <T> void addValue(T value) {
if(valueList == null){
valueList = getList(value.getClass());
}
valueList.add(value);
}
private <T> List<T> getList(Class<T> requiredType) {
return new ArrayList<>();
}
}
public static void main(String[] args) {
Sensordevice sd = new Sensordevice();
sd.addValue(new Object());
sd.addValue(new Integer(3));
sd.addValue("");
sd.addValue(new Sensordevice());
System.out.println(sd.getList(Sensordevice.class));
}
So if you don't know particular type would you class use, make your class generic:
public class Sensordevice<T> {
private List<T> valueList;
public void setValueList(List<T> valueList) {
this.valueList = valueList;
}
public void addValue(T value) {
if(valueList == null){
valueList = getList(value.getClass());
}
valueList.add(value);
}
private List<T> getList() {
return new ArrayList<T>();
}
}
If you don't know the List type you can leave it without any type specification, just put: private List valueList;
Change the valueList to: private List valueList; and getList() to:
private <T> List<Object> getList(Class<T> requiredType) {
return new ArrayList<Object>();
}
This fixes the error and it appears to work properly.
I tested it with strings, floats, and ints.

Categories