I have a Book class and then I make a List<Book>
. I have a problem with checking all attributes. The following is an example of program code for a class Book
:
class Book {
int id;
String name,author;
public Book(int id, String name, String author) {
this.id = id;
this.name = name;
this.author = author;
}
}
Here's the code snippet on the List<Book>
:
Book b = new Book(1, "", "Ok");
Book c = new Book(2, "Z", "");
Book d = new Book(0, "C", "Ok");
List<Book> x = new ArrayList<>();
x.add(b);
x.add(c);
x.add(d);
How to check if a value is string empty or null in a List<Book>
and then return Boolean & return message example id 2 has empty value
?
CodePudding user response:
You can use the StringUtils.isEmpty(...)
method from Apache Commons, or if you don't want the dependency you can write it your on like this:
public static boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
To check all authors
in the List
use Streams:
public boolean anyAuthorEmpty(List<Book> books) {
return books.stream().anyMatch(b -> isEmpty(b.getAuthor());
}
To find the exact Book
you can use .findFirst()
like this:
public Book findBookWithEmptyAuthor(List<Book> books) {
return books.stream().filter(b -> isEmpty(b.getAuthor())
.findFirst().orElse(null);
}
This will return the Book
or null
if none found.
If you need all with no author you can use Collectors.toList()
:
public List<Book> findBooksWithNoAuthor(List<Book> books) {
return books.stream().filter(b -> isEmpty(b.getAuthor())
.collect(Collectors.toList());
CodePudding user response:
To check multiple attributes of the class Book
the following solution ,may be offered (providing that there is implementation of the helper method isNullOrEmpty
):
class SONullEmpty {
static boolean isNullOrEmpty(String str) {
return str == null || str.isEmpty();
}
static List<Book> booksWithNullOrEmpty(List<Book> books) {
return books
.stream()
.filter(book -> Stream.of(
book.getName(), book.getAuthor()
).anyMatch(SONullEmpty::isNullOrEmpty)
)
.collect(Collectors.toList());
}
}
Similarly, a method accepting multiple getters of the Book
attributes may be implemented and then called:
// in the same SONullEmpty class
static List<Book> withNullOrEmptyAttribs(List<Book> books, Function<Book, String> ... getters) {
return books
.stream()
.filter(book -> Arrays.stream(getters).anyMatch(g -> isNullOrEmpty(g.apply(book))))
.collect(Collectors.toList());
}
Test:
Book b = new Book(1, "", "Ok");
Book c = new Book(2, "Z", "");
Book d = new Book(3, null, "Ok");
List<Book> x = Arrays.asList(b, c, d);
withNullOrEmptyAttribs(x, Book::getName)
.forEach(book -> System.out.printf("Book with id=%d has null or empty name%n", book.getId()));
withNullOrEmptyAttribs(x, Book::getAuthor)
.forEach(book -> System.out.printf("Book with id=%d has null or empty author%n", book.getId()));
Output:
Book with id=1 has null or empty name
Book with id=3 has null or empty name
Book with id=2 has null or empty author
CodePudding user response:
You can use reflection so that you do not need to manually test each filed separately:
static void testAllFieldsForNull(List<Book> bookList) throws IllegalAccessException {
for (int i = 0; i < bookList.size(); i ){
Book book = bookList.get(i);
Field[] fields = book.getClass().getDeclaredFields();
for(Field field: fields){
Class<?> fieldType = field.getType();
if(!fieldType.isPrimitive()){
if (field.get(book) == null){
System.out.println("Field [" field.getName() "] has null value for book at position " i);
continue;
}
if(fieldType.isAssignableFrom(String.class) && ((String)field.get(book)).isEmpty()){
System.out.println("Field [" field.getName() "] is empty String for book at position " i);
}
}
}
}
}
Test:
public static void main(String[] args) throws IllegalAccessException {
Book b = new Book(1, "", "Ok");
Book c = new Book(2, "Z", "");
Book d = new Book(0, "C", null);
List<Book> x = new ArrayList<>();
x.add(b);
x.add(c);
x.add(d);
testAllFieldsForNull(x);
}
Output:
Field [name] is empty String for book at position 0
Field [author] is empty String for book at position 1
Field [author] has null value for book at position 2
OR if you need to just collect "good" books (actually any sort of oject) you can use:
public static boolean testObject(Object obj){
Field[] fields = obj.getClass().getDeclaredFields();
boolean okay = true;
for(Field field: fields){
Class<?> fieldType = field.getType();
try{
if(!fieldType.isPrimitive()){
if (field.get(obj) == null){
okay = false;
continue;
}
if(fieldType.isAssignableFrom(String.class) && ((String)field.get(obj)).isEmpty()){
okay = false;
}
}
}catch (IllegalAccessException e){
e.printStackTrace();
return false;
}
}
return okay;
}
and then use that for filtering:
public static void main(String[] args) throws IllegalAccessException {
Book b = new Book(1, "", "Ok");
Book c = new Book(2, "Z", "");
Book d = new Book(0, "C", null);
Book a = new Book(3, "C", "D");
List<Book> x = new ArrayList<>();
x.add(b);
x.add(c);
x.add(d);
x.add(a);
System.out.println(
x
.stream()
.filter(FieldTest::testObject)
.collect(Collectors.toList()).get(0).id
);
}
CodePudding user response:
Or you can use Java Stream perhaps
public class Test1 {
private Test1()
{
Book b = new Book(1, "", "Ok");
Book c = new Book(2, "Z", "");
Book d = new Book(3, "C", "Ok");
List<Book> x = new ArrayList<>();
x.add(b);
x.add(c);
x.add(d);
boolean empty = x.stream()
.filter(book -> book.name == null || book.name.isEmpty() || book.author == null || book.author.isEmpty())
.count() > 0;
}
class Book
{
int id;
String name, author;
public Book(int id, String name, String author)
{
this.id = id;
this.name = name;
this.author = author;
}
}
public static void main(String[] args)
{
new Test1();
}
}
CodePudding user response:
so if you need to check if the string is null or empty you can go for
//code
String s = "somestring" if(s == "" || s == null){ //true }